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