1 /*
2  * Copyright (C) 2011 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 android.provider;
18 
19 import android.Manifest;
20 import android.annotation.SdkConstant;
21 import android.annotation.SdkConstant.SdkConstantType;
22 import android.content.ComponentName;
23 import android.content.ContentResolver;
24 import android.content.ContentValues;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.database.ContentObserver;
28 import android.net.Uri;
29 import android.provider.CallLog.Calls;
30 import android.telecom.PhoneAccount;
31 import android.telecom.PhoneAccountHandle;
32 import android.telecom.Voicemail;
33 
34 import java.util.List;
35 
36 /**
37  * The contract between the voicemail provider and applications. Contains
38  * definitions for the supported URIs and columns.
39  *
40  * <P>The content providers exposes two tables through this interface:
41  * <ul>
42  *   <li> Voicemails table: This stores the actual voicemail records. The
43  *   columns and URIs for accessing this table are defined by the
44  *   {@link Voicemails} class.
45  *   </li>
46  *   <li> Status table: This provides a way for the voicemail source application
47  *   to convey its current state to the system. The columns and URIS for
48  *   accessing this table are defined by the {@link Status} class.
49  *   </li>
50  * </ul>
51  *
52  * <P> The minimum permission needed to access this content provider is
53  * {@link Manifest.permission#ADD_VOICEMAIL}
54  *
55  * <P>Voicemails are inserted by what is called as a "voicemail source"
56  * application, which is responsible for syncing voicemail data between a remote
57  * server and the local voicemail content provider. "voicemail source"
58  * application should always set the {@link #PARAM_KEY_SOURCE_PACKAGE} in the
59  * URI to identify its package.
60  *
61  * <P>In addition to the {@link ContentObserver} notifications the voicemail
62  * provider also generates broadcast intents to notify change for applications
63  * that are not active and therefore cannot listen to ContentObserver
64  * notifications. Broadcast intents with following actions are generated:
65  * <ul>
66  *   <li> {@link #ACTION_NEW_VOICEMAIL} is generated for each new voicemail
67  *   inserted.
68  *   </li>
69  *   <li> {@link Intent#ACTION_PROVIDER_CHANGED} is generated for any change
70  *    made into the database, including new voicemail.
71  *   </li>
72  * </ul>
73  */
74 public class VoicemailContract {
75     /** Not instantiable. */
VoicemailContract()76     private VoicemailContract() {
77     }
78 
79     /** The authority used by the voicemail provider. */
80     public static final String AUTHORITY = "com.android.voicemail";
81     /**
82      * Parameter key used in the URI to specify the voicemail source package name.
83      * <p> This field must be set in all requests that originate from a voicemail source.
84      */
85     public static final String PARAM_KEY_SOURCE_PACKAGE = "source_package";
86 
87     /** Broadcast intent when a new voicemail record is inserted. */
88     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
89     public static final String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
90 
91     /**
92      * Broadcast intent to request a voicemail source to fetch voicemail content of a specific
93      * voicemail from the remote server. The voicemail to fetch is specified by the data uri
94      * of the intent.
95      * <p>
96      * All voicemail sources are expected to handle this event. After storing the content
97      * the application should also set {@link Voicemails#HAS_CONTENT} to 1;
98      */
99     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
100     public static final String ACTION_FETCH_VOICEMAIL = "android.intent.action.FETCH_VOICEMAIL";
101 
102     /**
103      * Broadcast intent to request all voicemail sources to perform a sync with the remote server.
104      */
105     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
106     public static final String ACTION_SYNC_VOICEMAIL = "android.provider.action.SYNC_VOICEMAIL";
107 
108     /**
109      * Broadcast intent to inform a new visual voicemail SMS has been received. This intent will
110      * only be delivered to the telephony service. {@link #EXTRA_VOICEMAIL_SMS} will be included.
111      */
112     /** @hide */
113     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
114     public static final String ACTION_VOICEMAIL_SMS_RECEIVED =
115             "com.android.internal.provider.action.VOICEMAIL_SMS_RECEIVED";
116 
117     /**
118      * Extra in {@link #ACTION_VOICEMAIL_SMS_RECEIVED} indicating the content of the SMS.
119      *
120      * @hide
121      */
122     public static final String EXTRA_VOICEMAIL_SMS = "android.provider.extra.VOICEMAIL_SMS";
123 
124     /**
125      * Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
126      * receiving package made this change.
127      */
128     public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
129 
130     /**
131      * Extra included in {@link #ACTION_SYNC_VOICEMAIL} broadcast intents to indicate which {@link
132      * PhoneAccountHandle} to sync.
133      */
134     public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
135             "android.provider.extra.PHONE_ACCOUNT_HANDLE";
136 
137     /**
138      * Name of the source package field, which must be same across all voicemail related tables.
139      * This is an internal field.
140      * @hide
141      */
142     public static final String SOURCE_PACKAGE_FIELD = "source_package";
143 
144     /** Defines fields exposed through the /voicemail path of this content provider. */
145     public static final class Voicemails implements BaseColumns, OpenableColumns {
146         /** Not instantiable. */
Voicemails()147         private Voicemails() {
148         }
149 
150         /** URI to insert/retrieve voicemails. */
151         public static final Uri CONTENT_URI =
152             Uri.parse("content://" + AUTHORITY + "/voicemail");
153 
154         /** The MIME type for a collection of voicemails. */
155         public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
156 
157         /** The MIME type for a single voicemail. */
158         public static final String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
159 
160         /**
161          * Phone number of the voicemail sender.
162          * <P>Type: TEXT</P>
163          */
164         public static final String NUMBER = Calls.NUMBER;
165         /**
166          * The date the voicemail was sent, in milliseconds since the epoch
167          * <P>Type: INTEGER (long)</P>
168          */
169         public static final String DATE = Calls.DATE;
170         /**
171          * The duration of the voicemail in seconds.
172          * <P>Type: INTEGER (long)</P>
173          */
174         public static final String DURATION = Calls.DURATION;
175         /**
176          * Whether this item has been read or otherwise consumed by the user.
177          * <P>Type: INTEGER (boolean)</P>
178          */
179         public static final String IS_READ = Calls.IS_READ;
180         /**
181          * The mail box state of the voicemail. This field is currently not used by the system.
182          * <P> Possible values: {@link #STATE_INBOX}, {@link #STATE_DELETED},
183          * {@link #STATE_UNDELETED}.
184          * <P>Type: INTEGER</P>
185          * @hide
186          */
187         public static final String STATE = "state";
188         /**
189          * Value of {@link #STATE} when the voicemail is in inbox.
190          * @hide
191          */
192         public static int STATE_INBOX = 0;
193         /**
194          * Value of {@link #STATE} when the voicemail has been marked as deleted.
195          * @hide
196          */
197         public static int STATE_DELETED = 1;
198         /**
199          * Value of {@link #STATE} when the voicemail has marked as undeleted.
200          * @hide
201          */
202         public static int STATE_UNDELETED = 2;
203         /**
204          * Package name of the source application that inserted the voicemail.
205          * <P>Type: TEXT</P>
206          */
207         public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD;
208         /**
209          * Application-specific data available to the source application that
210          * inserted the voicemail. This is typically used to store the source
211          * specific message id to identify this voicemail on the remote
212          * voicemail server.
213          * <P>Type: TEXT</P>
214          * <P> Note that this is NOT the voicemail media content data.
215          */
216         public static final String SOURCE_DATA = "source_data";
217         /**
218          * Whether the media content for this voicemail is available for
219          * consumption.
220          * <P>Type: INTEGER (boolean)</P>
221          */
222         public static final String HAS_CONTENT = "has_content";
223         /**
224          * MIME type of the media content for the voicemail.
225          * <P>Type: TEXT</P>
226          */
227         public static final String MIME_TYPE = "mime_type";
228         /**
229          * The transcription of the voicemail entry. This will only be populated if the voicemail
230          * entry has a valid transcription.
231          * <P>Type: TEXT</P>
232          */
233         public static final String TRANSCRIPTION = "transcription";
234         /**
235          * The state of the voicemail transcription.
236          * <P> Possible values: {@link #TRANSCRIPTION_NOT_STARTED},
237          * {@link #TRANSCRIPTION_IN_PROGRESS}, {@link #TRANSCRIPTION_FAILED},
238          * {@link #TRANSCRIPTION_AVAILABLE}.
239          * <P>Type: INTEGER</P>
240          * @hide
241          */
242         public static final String TRANSCRIPTION_STATE = "transcription_state";
243         /**
244          * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has not yet
245          * been attempted.
246          * @hide
247          */
248         public static final int TRANSCRIPTION_NOT_STARTED = 0;
249         /**
250          * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has begun
251          * but is not yet complete.
252          * @hide
253          */
254         public static final int TRANSCRIPTION_IN_PROGRESS = 1;
255         /**
256          * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has
257          * been attempted and failed.
258          * @hide
259          */
260         public static final int TRANSCRIPTION_FAILED = 2;
261         /**
262          * Value of {@link #TRANSCRIPTION_STATE} when the voicemail transcription has
263          * completed and the result has been stored in the {@link #TRANSCRIPTION} column.
264          * @hide
265          */
266         public static final int TRANSCRIPTION_AVAILABLE = 3;
267         /**
268          * Path to the media content file. Internal only field.
269          * @hide
270          */
271         public static final String _DATA = "_data";
272 
273         // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
274         // that was encoded into call log databases.
275 
276         /**
277          * The {@link ComponentName} of the {@link PhoneAccount} in string form. The
278          * {@link PhoneAccount} of the voicemail is used to differentiate voicemails from different
279          * sources.
280          * <P>Type: TEXT</P>
281          */
282         public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
283 
284         /**
285          * The identifier of a {@link PhoneAccount} that is unique to a specified
286          * {@link ComponentName}. The {@link PhoneAccount} of the voicemail is used to differentiate
287          * voicemails from different sources.
288          * <P>Type: TEXT</P>
289          */
290         public static final String PHONE_ACCOUNT_ID = "subscription_id";
291 
292         /**
293          * Flag used to indicate that local, unsynced changes are present.
294          * Currently, this is used to indicate that the voicemail was read or deleted.
295          * The value will be 1 if dirty is true, 0 if false.
296          * <P>Type: INTEGER (boolean)</P>
297          */
298         public static final String DIRTY = "dirty";
299 
300         /**
301          * Flag used to indicate that the voicemail was deleted but not synced to the server.
302          * A deleted row should be ignored.
303          * The value will be 1 if deleted is true, 0 if false.
304          * <P>Type: INTEGER (boolean)</P>
305          */
306         public static final String DELETED = "deleted";
307 
308         /**
309          * The date the row is last inserted, updated, or marked as deleted, in milliseconds
310          * since the epoch. Read only.
311          * <P>Type: INTEGER (long)</P>
312          */
313         public static final String LAST_MODIFIED = "last_modified";
314 
315         /**
316          * Flag to indicate the voicemail was backed up. The value will be 1 if backed up, 0 if
317          * not.
318          *
319          * <P>Type: INTEGER (boolean)</P>
320          */
321         public static final String BACKED_UP = "backed_up";
322 
323         /**
324          * Flag to indicate the voicemail was restored from a backup. The value will be 1 if
325          * restored, 0 if not.
326          *
327          * <P>Type: INTEGER (boolean)</P>
328          */
329         public static final String RESTORED = "restored";
330 
331         /**
332          * Flag to indicate the voicemail was marked as archived. Archived voicemail should not be
333          * deleted even if it no longer exist on the server. The value will be 1 if archived true, 0
334          * if not.
335          *
336          * <P>Type: INTEGER (boolean)</P>
337          */
338         public static final String ARCHIVED = "archived";
339 
340         /**
341          * Flag to indicate the voicemail is a OMTP voicemail handled by the {@link
342          * android.telephony.VisualVoicemailService}. The UI should only show OMTP voicemails from
343          * the current visual voicemail package. For example, the selection could be
344          * {@code WHERE (IS_OMTP_VOICEMAIL == 0) OR ( IS_OMTP_VOICEMAIL == 1 AND SOURCE_PACKAGE ==
345          * "current.vvm.package")}
346          *
347          * <P>Type: INTEGER (boolean)</P>
348          *
349          * @see android.telephony.TelephonyManager#getVisualVoicemailPackageName
350          */
351         public static final String IS_OMTP_VOICEMAIL = "is_omtp_voicemail";
352 
353         /**
354          * A convenience method to build voicemail URI specific to a source package by appending
355          * {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
356          */
buildSourceUri(String packageName)357         public static Uri buildSourceUri(String packageName) {
358             return Voicemails.CONTENT_URI.buildUpon()
359                     .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName)
360                     .build();
361         }
362 
363         /**
364          * Inserts a new voicemail into the voicemail content provider.
365          *
366          * @param context The context of the app doing the inserting
367          * @param voicemail Data to be inserted
368          * @return {@link Uri} of the newly inserted {@link Voicemail}
369          *
370          * @hide
371          */
insert(Context context, Voicemail voicemail)372         public static Uri insert(Context context, Voicemail voicemail) {
373             ContentResolver contentResolver = context.getContentResolver();
374             ContentValues contentValues = getContentValues(voicemail);
375             return contentResolver.insert(buildSourceUri(context.getPackageName()), contentValues);
376         }
377 
378         /**
379          * Inserts a list of voicemails into the voicemail content provider.
380          *
381          * @param context The context of the app doing the inserting
382          * @param voicemails Data to be inserted
383          * @return the number of voicemails inserted
384          *
385          * @hide
386          */
insert(Context context, List<Voicemail> voicemails)387         public static int insert(Context context, List<Voicemail> voicemails) {
388             ContentResolver contentResolver = context.getContentResolver();
389             int count = voicemails.size();
390             for (int i = 0; i < count; i++) {
391                 ContentValues contentValues = getContentValues(voicemails.get(i));
392                 contentResolver.insert(buildSourceUri(context.getPackageName()), contentValues);
393             }
394             return count;
395         }
396 
397         /**
398          * Clears all voicemails accessible to this voicemail content provider for the calling
399          * package. By default, a package only has permission to delete voicemails it inserted.
400          *
401          * @return the number of voicemails deleted
402          *
403          * @hide
404          */
deleteAll(Context context)405         public static int deleteAll(Context context) {
406             return context.getContentResolver().delete(
407                     buildSourceUri(context.getPackageName()), "", new String[0]);
408         }
409 
410         /**
411          * Maps structured {@link Voicemail} to {@link ContentValues} in content provider.
412          */
getContentValues(Voicemail voicemail)413         private static ContentValues getContentValues(Voicemail voicemail) {
414             ContentValues contentValues = new ContentValues();
415             contentValues.put(Voicemails.DATE, String.valueOf(voicemail.getTimestampMillis()));
416             contentValues.put(Voicemails.NUMBER, voicemail.getNumber());
417             contentValues.put(Voicemails.DURATION, String.valueOf(voicemail.getDuration()));
418             contentValues.put(Voicemails.SOURCE_PACKAGE, voicemail.getSourcePackage());
419             contentValues.put(Voicemails.SOURCE_DATA, voicemail.getSourceData());
420             contentValues.put(Voicemails.IS_READ, voicemail.isRead() ? 1 : 0);
421 
422             PhoneAccountHandle phoneAccount = voicemail.getPhoneAccount();
423             if (phoneAccount != null) {
424                 contentValues.put(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME,
425                         phoneAccount.getComponentName().flattenToString());
426                 contentValues.put(Voicemails.PHONE_ACCOUNT_ID, phoneAccount.getId());
427             }
428 
429             if (voicemail.getTranscription() != null) {
430                 contentValues.put(Voicemails.TRANSCRIPTION, voicemail.getTranscription());
431             }
432 
433             return contentValues;
434         }
435     }
436 
437     /** Defines fields exposed through the /status path of this content provider. */
438     public static final class Status implements BaseColumns {
439         /** URI to insert/retrieve status of voicemail source. */
440         public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/status");
441         /** The MIME type for a collection of voicemail source statuses. */
442         public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
443         /** The MIME type for a single voicemail source status entry. */
444         public static final String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
445 
446         /** Not instantiable. */
Status()447         private Status() {
448         }
449         /**
450          * The package name of the voicemail source. There can only be a one entry per account
451          * per source.
452          * <P>Type: TEXT</P>
453          */
454         public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD;
455 
456         /**
457          * The type of the source, which determines how to interpret source-specific states.
458          * Typically this will be set to the same string as
459          * {@link android.telephony.CarrierConfigManager#KEY_VVM_TYPE_STRING}. For example,
460          * "vvm_type_omtp".
461          *
462          * <P>Type: TEXT</P>
463          *
464          * @see #CONFIGURATION_STATE
465          * @see #DATA_CHANNEL_STATE
466          * @see #NOTIFICATION_CHANNEL_STATE
467          */
468         public static final String SOURCE_TYPE = "source_type";
469 
470         // Note: Multiple entries may exist for a single source if they are differentiated by the
471         // PHONE_ACCOUNT_* fields.
472 
473         /**
474          * The {@link ComponentName} of the {@link PhoneAccount} in string form. The
475          * {@link PhoneAccount} differentiates voicemail sources from the same package.
476          * <P>Type: TEXT</P>
477          */
478         public static final String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
479 
480         /**
481          * The identifier of a {@link PhoneAccount} that is unique to a specified component. The
482          * {@link PhoneAccount} differentiates voicemail sources from the same package.
483          * <P>Type: TEXT</P>
484          */
485         public static final String PHONE_ACCOUNT_ID = "phone_account_id";
486 
487         /**
488          * The URI to call to invoke source specific voicemail settings screen. On a user request
489          * to setup voicemail an intent with action VIEW with this URI will be fired by the system.
490          * <P>Type: TEXT</P>
491          */
492         public static final String SETTINGS_URI = "settings_uri";
493         /**
494          * The URI to call when the user requests to directly access the voicemail from the remote
495          * server. In case of an IVR voicemail system this is typically set to the the voicemail
496          * number specified using a tel:/ URI.
497          * <P>Type: TEXT</P>
498          */
499         public static final String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
500         /**
501          * The configuration state of the voicemail source.
502          *
503          * <P>Negative values are reserved to the source for source-specific states, see
504          * {@link #SOURCE_TYPE}
505          *
506          * <P> Possible values:
507          * {@link #CONFIGURATION_STATE_OK},
508          * {@link #CONFIGURATION_STATE_NOT_CONFIGURED},
509          * {@link #CONFIGURATION_STATE_CAN_BE_CONFIGURED}
510          * {@link #CONFIGURATION_STATE_CONFIGURING}
511          * {@link #CONFIGURATION_STATE_FAILED}
512          * {@link #CONFIGURATION_STATE_DISABLED}
513          * <P>Type: INTEGER</P>
514          */
515         public static final String CONFIGURATION_STATE = "configuration_state";
516 
517         /** Value of {@link #CONFIGURATION_STATE} to indicate an all OK configuration status. */
518         public static final int CONFIGURATION_STATE_OK = 0;
519         /**
520          * Value of {@link #CONFIGURATION_STATE} to indicate the visual voicemail is not
521          * yet configured on this device.
522          */
523         public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1;
524         /**
525          * Value of {@link #CONFIGURATION_STATE} to indicate the visual voicemail is not
526          * yet configured on this device but can be configured by the user.
527          * <p> This state must be used when the source has verified that the current user can be
528          * upgraded to visual voicemail and would like to show a set up invitation message.
529          */
530         public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2;
531         /**
532          * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail still is being
533          * configured.
534          */
535         public static final int CONFIGURATION_STATE_CONFIGURING = 3;
536         /**
537          * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail has failed to
538          * be configured.
539          */
540         public static final int CONFIGURATION_STATE_FAILED = 4;
541         /**
542          * Value of {@link #CONFIGURATION_STATE} to indicate that visual voicemail is disabled by
543          * the user.
544          */
545         public static final int CONFIGURATION_STATE_DISABLED = 5;
546         /**
547          * The data channel state of the voicemail source. This the channel through which the source
548          * pulls voicemail data from a remote server.
549          *
550          * <P>Negative values are reserved to the source for source-specific states, see
551          * {@link #SOURCE_TYPE}
552          *
553          * <P> Possible values:
554          * {@link #DATA_CHANNEL_STATE_OK},
555          * {@link #DATA_CHANNEL_STATE_NO_CONNECTION}
556          * </P>
557          * <P>Type: INTEGER</P>
558          */
559         public static final String DATA_CHANNEL_STATE = "data_channel_state";
560 
561         /**
562          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel is working fine.
563          */
564         public static final int DATA_CHANNEL_STATE_OK = 0;
565         /**
566          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel failed to find a
567          *  suitable network to connect to the server.
568          */
569         public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1;
570         /**
571          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel failed to find a
572          *  suitable network to connect to the server, and the carrier requires using cellular
573          *  data network to connect to the server.
574          */
575         public static final int DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED = 2;
576         /**
577          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel received incorrect
578          *  settings or credentials to connect to the server
579          */
580         public static final int DATA_CHANNEL_STATE_BAD_CONFIGURATION = 3;
581         /**
582          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that a error has occurred in the data
583          *  channel while communicating with the server
584          */
585         public static final int DATA_CHANNEL_STATE_COMMUNICATION_ERROR = 4;
586         /**
587          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that the server reported an internal
588          *  error to the data channel.
589          */
590         public static final int DATA_CHANNEL_STATE_SERVER_ERROR = 5;
591         /**
592          *  Value of {@link #DATA_CHANNEL_STATE} to indicate that while there is a suitable network,
593          *  the data channel is unable to establish a connection with the server.
594          */
595         public static final int DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR = 6;
596 
597         /**
598          * The notification channel state of the voicemail source. This is the channel through which
599          * the source gets notified of new voicemails on the remote server.
600          *
601          * <P>Negative values are reserved to the source for source-specific states, see
602          * {@link #SOURCE_TYPE}
603          *
604          * <P> Possible values:
605          * {@link #NOTIFICATION_CHANNEL_STATE_OK},
606          * {@link #NOTIFICATION_CHANNEL_STATE_NO_CONNECTION},
607          * {@link #NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING}
608          * </P>
609          * <P>Type: INTEGER</P>
610          */
611         public static final String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
612 
613         /**
614          * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel is
615          * working fine.
616          */
617         public static final int NOTIFICATION_CHANNEL_STATE_OK = 0;
618         /**
619          * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel
620          * connection is not working.
621          */
622         public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1;
623         /**
624          * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that there are messages waiting
625          * on the server but the details are not known.
626          * <p> Use this state when the notification can only tell that there are pending messages on
627          * the server but no details of the sender/time etc are known.
628          */
629         public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2;
630 
631         /**
632          * Amount of resource that is used by existing voicemail in the visual voicemail inbox,
633          * or {@link #QUOTA_UNAVAILABLE} if the quota has never been updated before. This value is
634          * used to inform the client the situation on the remote server. Unit is not specified.
635          * <P>Type: INTEGER</P>
636          */
637         public static final String QUOTA_OCCUPIED = "quota_occupied";
638 
639         /**
640          * Total resource in the visual voicemail inbox that can be used, or
641          * {@link #QUOTA_UNAVAILABLE} if server either has unlimited quota or does not provide quota
642          * information. This value is used to inform the client the situation on the remote server.
643          * Unit is not specified.
644          * <P>Type: INTEGER</P>
645          */
646         public static final String QUOTA_TOTAL = "quota_total";
647 
648         /**
649          * Value for {@link #QUOTA_OCCUPIED} and {@link #QUOTA_TOTAL} to indicate that no
650          * information is available.
651          */
652         public static final int QUOTA_UNAVAILABLE = -1;
653 
654         /**
655          * A convenience method to build status URI specific to a source package by appending
656          * {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
657          */
buildSourceUri(String packageName)658         public static Uri buildSourceUri(String packageName) {
659             return Status.CONTENT_URI.buildUpon()
660                     .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build();
661         }
662     }
663 }
664