[go: nahoru, domu]

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