Home | History | Annotate | Download | only in provider
      1 /*
      2  * Copyright (C) 2007 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.im.provider;
     18 
     19 import android.content.ContentQueryMap;
     20 import android.content.ContentResolver;
     21 import android.content.ContentUris;
     22 import android.content.ContentValues;
     23 import android.database.Cursor;
     24 import android.net.Uri;
     25 import android.os.Handler;
     26 import android.provider.BaseColumns;
     27 
     28 import java.util.HashMap;
     29 
     30 /**
     31  * The IM provider stores all information about roster contacts, chat messages, presence, etc.
     32  *
     33  * @hide
     34  */
     35 public class Imps {
     36     /**
     37      * no public constructor since this is a utility class
     38      */
     39     private Imps() {}
     40 
     41     /**
     42      * The Columns for IM providers (i.e. AIM, Y!, GTalk)
     43      */
     44     public interface ProviderColumns {
     45         /**
     46          * The name of the IM provider
     47          * <P>Type: TEXT</P>
     48          */
     49         String NAME = "name";
     50 
     51         /**
     52          * The full name of the provider
     53          * <P>Type: TEXT</P>
     54          */
     55         String FULLNAME = "fullname";
     56 
     57         /**
     58          * The category for the provider, used to form intent.
     59          * <P>Type: TEXT</P>
     60          */
     61         String CATEGORY = "category";
     62 
     63         /**
     64          * The url users should visit to create a new account for this provider
     65          * <P>Type: TEXT</P>
     66          */
     67         String SIGNUP_URL = "signup_url";
     68     }
     69 
     70     /**
     71      * Known names corresponding to the {@link ProviderColumns#NAME} column
     72      */
     73     public interface ProviderNames {
     74         //
     75         //NOTE: update Contacts.java with new providers when they're added.
     76         //
     77         String YAHOO = "Yahoo";
     78         String GTALK = "GTalk";
     79         String MSN = "MSN";
     80         String ICQ = "ICQ";
     81         String AIM = "AIM";
     82         String XMPP = "XMPP";
     83         String JABBER = "JABBER";
     84         String SKYPE = "SKYPE";
     85         String QQ = "QQ";
     86     }
     87 
     88     /**
     89      * This table contains the IM providers
     90      */
     91     public static final class Provider implements BaseColumns, ProviderColumns {
     92         private Provider() {}
     93 
     94         public static final long getProviderIdForName(ContentResolver cr, String providerName) {
     95             String[] selectionArgs = new String[1];
     96             selectionArgs[0] = providerName;
     97 
     98             Cursor cursor = cr.query(CONTENT_URI,
     99                     PROVIDER_PROJECTION,
    100                     NAME+"=?",
    101                     selectionArgs, null);
    102 
    103             long retVal = 0;
    104             try {
    105                 if (cursor.moveToFirst()) {
    106                     retVal = cursor.getLong(cursor.getColumnIndexOrThrow(_ID));
    107                 }
    108             } finally {
    109                 cursor.close();
    110             }
    111 
    112             return retVal;
    113         }
    114 
    115         public static final String getProviderNameForId(ContentResolver cr, long providerId) {
    116             Cursor cursor = cr.query(CONTENT_URI,
    117                     PROVIDER_PROJECTION,
    118                     _ID + "=" + providerId,
    119                     null, null);
    120 
    121             String retVal = null;
    122             try {
    123                 if (cursor.moveToFirst()) {
    124                     retVal = cursor.getString(cursor.getColumnIndexOrThrow(NAME));
    125                 }
    126             } finally {
    127                 cursor.close();
    128             }
    129 
    130             return retVal;
    131         }
    132 
    133         private static final String[] PROVIDER_PROJECTION = new String[] {
    134                 _ID,
    135                 NAME
    136         };
    137 
    138         public static final String ACTIVE_ACCOUNT_ID = "account_id";
    139         public static final String ACTIVE_ACCOUNT_USERNAME = "account_username";
    140         public static final String ACTIVE_ACCOUNT_PW = "account_pw";
    141         public static final String ACTIVE_ACCOUNT_LOCKED = "account_locked";
    142         public static final String ACTIVE_ACCOUNT_KEEP_SIGNED_IN = "account_keepSignedIn";
    143         public static final String ACCOUNT_PRESENCE_STATUS = "account_presenceStatus";
    144         public static final String ACCOUNT_CONNECTION_STATUS = "account_connStatus";
    145 
    146         /**
    147          * The content:// style URL for this table
    148          */
    149         public static final Uri CONTENT_URI =
    150             Uri.parse("content://imps/providers");
    151 
    152         public static final Uri CONTENT_URI_WITH_ACCOUNT =
    153             Uri.parse("content://imps/providers/account");
    154 
    155         /**
    156          * The MIME type of {@link #CONTENT_URI} providing a directory of
    157          * people.
    158          */
    159         public static final String CONTENT_TYPE =
    160                 "vnd.android.cursor.dir/imps-providers";
    161 
    162         public static final String CONTENT_ITEM_TYPE =
    163                 "vnd.android.cursor.item/imps-providers";
    164 
    165         /**
    166          * The default sort order for this table
    167          */
    168         public static final String DEFAULT_SORT_ORDER = "name ASC";
    169     }
    170 
    171     /**
    172      * The columns for IM accounts. There can be more than one account for each IM provider.
    173      */
    174     public interface AccountColumns {
    175         /**
    176          * The name of the account
    177          * <P>Type: TEXT</P>
    178          */
    179         String NAME = "name";
    180 
    181         /**
    182          * The IM provider for this account
    183          * <P>Type: INTEGER</P>
    184          */
    185         String PROVIDER = "provider";
    186 
    187         /**
    188          * The username for this account
    189          * <P>Type: TEXT</P>
    190          */
    191         String USERNAME = "username";
    192 
    193         /**
    194          * The password for this account
    195          * <P>Type: TEXT</P>
    196          */
    197         String PASSWORD = "pw";
    198 
    199         /**
    200          * A boolean value indicates if the account is active.
    201          * <P>Type: INTEGER</P>
    202          */
    203         String ACTIVE = "active";
    204 
    205         /**
    206          * A boolean value indicates if the account is locked (not editable)
    207          * <P>Type: INTEGER</P>
    208          */
    209         String LOCKED = "locked";
    210 
    211         /**
    212          * A boolean value to indicate whether this account is kept signed in.
    213          * <P>Type: INTEGER</P>
    214          */
    215         String KEEP_SIGNED_IN = "keep_signed_in";
    216 
    217         /**
    218          * A boolean value indiciating the last login state for this account
    219          * <P>Type: INTEGER</P>
    220          */
    221         String LAST_LOGIN_STATE = "last_login_state";
    222     }
    223 
    224     /**
    225      * This table contains the IM accounts.
    226      */
    227     public static final class Account implements BaseColumns, AccountColumns {
    228         private Account() {}
    229 
    230         public static final long getProviderIdForAccount(ContentResolver cr, long accountId) {
    231             Cursor cursor = cr.query(CONTENT_URI,
    232                     PROVIDER_PROJECTION,
    233                     _ID + "=" + accountId,
    234                     null /* selection args */,
    235                     null /* sort order */);
    236 
    237             long providerId = 0;
    238 
    239             try {
    240                 if (cursor.moveToFirst()) {
    241                     providerId = cursor.getLong(PROVIDER_COLUMN);
    242                 }
    243             } finally {
    244                 cursor.close();
    245             }
    246 
    247             return providerId;
    248         }
    249 
    250         private static final String[] PROVIDER_PROJECTION = new String[] { PROVIDER };
    251         private static final int PROVIDER_COLUMN = 0;
    252 
    253         /**
    254          * The content:// style URL for this table
    255          */
    256         public static final Uri CONTENT_URI =
    257             Uri.parse("content://imps/accounts");
    258 
    259         /**
    260          * The MIME type of {@link #CONTENT_URI} providing a directory of
    261          * account.
    262          */
    263         public static final String CONTENT_TYPE =
    264                 "vnd.android.cursor.dir/imps-accounts";
    265 
    266         /**
    267          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
    268          * account.
    269          */
    270         public static final String CONTENT_ITEM_TYPE =
    271                 "vnd.android.cursor.item/imps-accounts";
    272 
    273         /**
    274          * The default sort order for this table
    275          */
    276         public static final String DEFAULT_SORT_ORDER = "name ASC";
    277 
    278     }
    279 
    280     /**
    281      * Connection status
    282      */
    283     public interface ConnectionStatus {
    284         /**
    285          * The connection is offline, not logged in.
    286          */
    287         int OFFLINE = 0;
    288 
    289         /**
    290          * The connection is attempting to connect.
    291          */
    292         int CONNECTING = 1;
    293 
    294         /**
    295          * The connection is suspended due to network not available.
    296          */
    297         int SUSPENDED = 2;
    298 
    299         /**
    300          * The connection is logged in and online.
    301          */
    302         int ONLINE = 3;
    303     }
    304 
    305     public interface AccountStatusColumns {
    306         /**
    307          * account id
    308          * <P>Type: INTEGER</P>
    309          */
    310         String ACCOUNT = "account";
    311 
    312         /**
    313          * User's presence status, see definitions in {#link CommonPresenceColumn}
    314          * <P>Type: INTEGER</P>
    315          */
    316         String PRESENCE_STATUS = "presenceStatus";
    317 
    318         /**
    319          * The connection status of this account, see {#link ConnectionStatus}
    320          * <P>Type: INTEGER</P>
    321          */
    322         String CONNECTION_STATUS = "connStatus";
    323     }
    324 
    325     public static final class AccountStatus implements BaseColumns, AccountStatusColumns {
    326         /**
    327          * The content:// style URL for this table
    328          */
    329         public static final Uri CONTENT_URI =
    330             Uri.parse("content://imps/accountStatus");
    331 
    332         /**
    333          * The MIME type of {@link #CONTENT_URI} providing a directory of account status.
    334          */
    335         public static final String CONTENT_TYPE =
    336                 "vnd.android.cursor.dir/imps-account-status";
    337 
    338         /**
    339          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single account status.
    340          */
    341         public static final String CONTENT_ITEM_TYPE =
    342                 "vnd.android.cursor.item/imps-account-status";
    343 
    344         /**
    345          * The default sort order for this table
    346          */
    347         public static final String DEFAULT_SORT_ORDER = "name ASC";
    348     }
    349 
    350     /**
    351      * Columns from the Contacts table.
    352      */
    353     public interface ContactsColumns {
    354         /**
    355          * The username
    356          * <P>Type: TEXT</P>
    357          */
    358         String USERNAME = "username";
    359 
    360         /**
    361          * The nickname or display name
    362          * <P>Type: TEXT</P>
    363          */
    364         String NICKNAME = "nickname";
    365 
    366         /**
    367          * The IM provider for this contact
    368          * <P>Type: INTEGER</P>
    369          */
    370         String PROVIDER = "provider";
    371 
    372         /**
    373          * The account (within a IM provider) for this contact
    374          * <P>Type: INTEGER</P>
    375          */
    376         String ACCOUNT = "account";
    377 
    378         /**
    379          * The contactList this contact belongs to
    380          * <P>Type: INTEGER</P>
    381          */
    382         String CONTACTLIST = "contactList";
    383 
    384         /**
    385          * Contact type
    386          * <P>Type: INTEGER</P>
    387          */
    388         String TYPE = "type";
    389 
    390         /**
    391          * normal IM contact
    392          */
    393         int TYPE_NORMAL = 0;
    394         /**
    395          * temporary contact, someone not in the list of contacts that we
    396          * subscribe presence for. Usually created because of the user is
    397          * having a chat session with this contact.
    398          */
    399         int TYPE_TEMPORARY = 1;
    400         /**
    401          * temporary contact created for group chat.
    402          */
    403         int TYPE_GROUP = 2;
    404         /**
    405          * blocked contact.
    406          */
    407         int TYPE_BLOCKED = 3;
    408         /**
    409          * the contact is hidden. The client should always display this contact to the user.
    410          */
    411         int TYPE_HIDDEN = 4;
    412         /**
    413          * the contact is pinned. The client should always display this contact to the user.
    414          */
    415         int TYPE_PINNED = 5;
    416 
    417         /**
    418          * Contact subscription status
    419          * <P>Type: INTEGER</P>
    420          */
    421         String SUBSCRIPTION_STATUS = "subscriptionStatus";
    422 
    423         /**
    424          * no pending subscription
    425          */
    426         int SUBSCRIPTION_STATUS_NONE = 0;
    427         /**
    428          * requested to subscribe
    429          */
    430         int SUBSCRIPTION_STATUS_SUBSCRIBE_PENDING = 1;
    431         /**
    432          * requested to unsubscribe
    433          */
    434         int SUBSCRIPTION_STATUS_UNSUBSCRIBE_PENDING = 2;
    435 
    436         /**
    437          * Contact subscription type
    438          * <P>Type: INTEGER </P>
    439          */
    440         String SUBSCRIPTION_TYPE = "subscriptionType";
    441 
    442         /**
    443          * The user and contact have no interest in each other's presence.
    444          */
    445         int SUBSCRIPTION_TYPE_NONE = 0;
    446         /**
    447          * The user wishes to stop receiving presence updates from the contact.
    448          */
    449         int SUBSCRIPTION_TYPE_REMOVE = 1;
    450         /**
    451          * The user is interested in receiving presence updates from the contact.
    452          */
    453         int SUBSCRIPTION_TYPE_TO = 2;
    454         /**
    455          * The contact is interested in receiving presence updates from the user.
    456          */
    457         int SUBSCRIPTION_TYPE_FROM = 3;
    458         /**
    459          * The user and contact have a mutual interest in each other's presence.
    460          */
    461         int SUBSCRIPTION_TYPE_BOTH = 4;
    462         /**
    463          * This is a special type reserved for pending subscription requests
    464          */
    465         int SUBSCRIPTION_TYPE_INVITATIONS = 5;
    466 
    467         /**
    468          * Quick Contact: derived from Google Contact Extension's "message_count" attribute.
    469          * <P>Type: INTEGER</P>
    470          */
    471         String QUICK_CONTACT = "qc";
    472 
    473         /**
    474          * Google Contact Extension attribute
    475          *
    476          * Rejected: a boolean value indicating whether a subscription request from
    477          * this client was ever rejected by the user. "true" indicates that it has.
    478          * This is provided so that a client can block repeated subscription requests.
    479          * <P>Type: INTEGER</P>
    480          */
    481         String REJECTED = "rejected";
    482 
    483         /**
    484          * Off The Record status: 0 for disabled, 1 for enabled
    485          * <P>Type: INTEGER </P>
    486          */
    487         String OTR = "otr";
    488     }
    489 
    490     /**
    491      * This defines the different type of values of {@link ContactsColumns#OTR}
    492      */
    493     public interface OffTheRecordType {
    494         /*
    495          * Off the record not turned on
    496          */
    497         int DISABLED = 0;
    498         /**
    499          * Off the record turned on, but we don't know who turned it on
    500          */
    501         int ENABLED = 1;
    502         /**
    503          * Off the record turned on by the user
    504          */
    505         int ENABLED_BY_USER = 2;
    506         /**
    507          * Off the record turned on by the buddy
    508          */
    509         int ENABLED_BY_BUDDY = 3;
    510     };
    511 
    512     /**
    513      * This table contains contacts.
    514      */
    515     public static final class Contacts implements BaseColumns,
    516             ContactsColumns, PresenceColumns, ChatsColumns {
    517         /**
    518          * no public constructor since this is a utility class
    519          */
    520         private Contacts() {}
    521 
    522         /**
    523          * The content:// style URL for this table
    524          */
    525         public static final Uri CONTENT_URI =
    526             Uri.parse("content://imps/contacts");
    527 
    528         /**
    529          * The content:// style URL for contacts joined with presence
    530          */
    531         public static final Uri CONTENT_URI_WITH_PRESENCE =
    532             Uri.parse("content://imps/contactsWithPresence");
    533 
    534         /**
    535          * The content:// style URL for barebone contacts, not joined with any other table
    536          */
    537         public static final Uri CONTENT_URI_CONTACTS_BAREBONE =
    538             Uri.parse("content://imps/contactsBarebone");
    539 
    540         /**
    541          * The content:// style URL for contacts who have an open chat session
    542          */
    543         public static final Uri CONTENT_URI_CHAT_CONTACTS =
    544             Uri.parse("content://imps/contacts/chatting");
    545 
    546         /**
    547          * The content:// style URL for contacts who have been blocked
    548          */
    549         public static final Uri CONTENT_URI_BLOCKED_CONTACTS =
    550             Uri.parse("content://imps/contacts/blocked");
    551 
    552         /**
    553          * The content:// style URL for contacts by provider and account
    554          */
    555         public static final Uri CONTENT_URI_CONTACTS_BY =
    556             Uri.parse("content://imps/contacts");
    557 
    558         /**
    559          * The content:// style URL for contacts by provider and account,
    560          * and who have an open chat session
    561          */
    562         public static final Uri CONTENT_URI_CHAT_CONTACTS_BY =
    563             Uri.parse("content://imps/contacts/chatting");
    564 
    565         /**
    566          * The content:// style URL for contacts by provider and account,
    567          * and who are online
    568          */
    569         public static final Uri CONTENT_URI_ONLINE_CONTACTS_BY =
    570             Uri.parse("content://imps/contacts/online");
    571 
    572         /**
    573          * The content:// style URL for contacts by provider and account,
    574          * and who are offline
    575          */
    576         public static final Uri CONTENT_URI_OFFLINE_CONTACTS_BY =
    577             Uri.parse("content://imps/contacts/offline");
    578 
    579         /**
    580          * The content:// style URL for operations on bulk contacts
    581          */
    582         public static final Uri BULK_CONTENT_URI =
    583                 Uri.parse("content://imps/bulk_contacts");
    584 
    585         /**
    586          * The content:// style URL for the count of online contacts in each
    587          * contact list by provider and account.
    588          */
    589         public static final Uri CONTENT_URI_ONLINE_COUNT =
    590             Uri.parse("content://imps/contacts/onlineCount");
    591 
    592         /**
    593          * The MIME type of {@link #CONTENT_URI} providing a directory of
    594          * people.
    595          */
    596         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-contacts";
    597 
    598         /**
    599          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
    600          * person.
    601          */
    602         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/imps-contacts";
    603 
    604         /**
    605          * The default sort order for this table
    606          */
    607         public static final String DEFAULT_SORT_ORDER =
    608                 "subscriptionType DESC, last_message_date DESC," +
    609                         " mode DESC, nickname COLLATE UNICODE ASC";
    610 
    611         public static final String CHATS_CONTACT = "chats_contact";
    612 
    613         public static final String AVATAR_HASH = "avatars_hash";
    614 
    615         public static final String AVATAR_DATA = "avatars_data";
    616     }
    617 
    618     /**
    619      * Columns from the ContactList table.
    620      */
    621     public interface ContactListColumns {
    622         String NAME = "name";
    623         String PROVIDER = "provider";
    624         String ACCOUNT = "account";
    625     }
    626 
    627     /**
    628      * This table contains the contact lists.
    629      */
    630     public static final class ContactList implements BaseColumns,
    631             ContactListColumns {
    632         private ContactList() {}
    633 
    634         /**
    635          * The content:// style URL for this table
    636          */
    637         public static final Uri CONTENT_URI =
    638             Uri.parse("content://imps/contactLists");
    639 
    640         /**
    641          * The MIME type of {@link #CONTENT_URI} providing a directory of
    642          * people.
    643          */
    644         public static final String CONTENT_TYPE =
    645                 "vnd.android.cursor.dir/imps-contactLists";
    646 
    647         /**
    648          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
    649          * person.
    650          */
    651         public static final String CONTENT_ITEM_TYPE =
    652                 "vnd.android.cursor.item/imps-contactLists";
    653 
    654         /**
    655          * The default sort order for this table
    656          */
    657         public static final String DEFAULT_SORT_ORDER = "name COLLATE UNICODE ASC";
    658 
    659         public static final String PROVIDER_NAME = "provider_name";
    660 
    661         public static final String ACCOUNT_NAME = "account_name";
    662     }
    663 
    664     /**
    665      * Columns from the BlockedList table.
    666      */
    667     public interface BlockedListColumns {
    668         /**
    669          * The username of the blocked contact.
    670          * <P>Type: TEXT</P>
    671          */
    672         String USERNAME = "username";
    673 
    674         /**
    675          * The nickname of the blocked contact.
    676          * <P>Type: TEXT</P>
    677          */
    678         String NICKNAME = "nickname";
    679 
    680         /**
    681          * The provider id of the blocked contact.
    682          * <P>Type: INT</P>
    683          */
    684         String PROVIDER = "provider";
    685 
    686         /**
    687          * The account id of the blocked contact.
    688          * <P>Type: INT</P>
    689          */
    690         String ACCOUNT = "account";
    691     }
    692 
    693     /**
    694      * This table contains blocked lists
    695      */
    696     public static final class BlockedList implements BaseColumns, BlockedListColumns {
    697         private BlockedList() {}
    698 
    699         /**
    700          * The content:// style URL for this table
    701          */
    702         public static final Uri CONTENT_URI =
    703             Uri.parse("content://imps/blockedList");
    704 
    705         /**
    706          * The MIME type of {@link #CONTENT_URI} providing a directory of
    707          * people.
    708          */
    709         public static final String CONTENT_TYPE =
    710                 "vnd.android.cursor.dir/imps-blockedList";
    711 
    712         /**
    713          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
    714          * person.
    715          */
    716         public static final String CONTENT_ITEM_TYPE =
    717                 "vnd.android.cursor.item/imps-blockedList";
    718 
    719         /**
    720          * The default sort order for this table
    721          */
    722         public static final String DEFAULT_SORT_ORDER = "nickname ASC";
    723 
    724         public static final String PROVIDER_NAME = "provider_name";
    725 
    726         public static final String ACCOUNT_NAME = "account_name";
    727 
    728         public static final String AVATAR_DATA = "avatars_data";
    729     }
    730 
    731     /**
    732      * Columns from the contactsEtag table
    733      */
    734     public interface ContactsEtagColumns {
    735         /**
    736          * The roster etag, computed by the server, stored on the client. There is one etag
    737          * per account roster.
    738          * <P>Type: TEXT</P>
    739          */
    740         String ETAG = "etag";
    741 
    742         /**
    743          * The OTR etag, computed by the server, stored on the client. There is one OTR etag
    744          * per account roster.
    745          * <P>Type: TEXT</P>
    746          */
    747         String OTR_ETAG = "otr_etag";
    748 
    749         /**
    750          * The account id for the etag.
    751          * <P> Type: INTEGER </P>
    752          */
    753         String ACCOUNT = "account";
    754     }
    755 
    756     public static final class ContactsEtag implements BaseColumns, ContactsEtagColumns {
    757         private ContactsEtag() {}
    758 
    759         public static final Cursor query(ContentResolver cr,
    760                 String[] projection) {
    761             return cr.query(CONTENT_URI, projection, null, null, null);
    762         }
    763 
    764         public static final Cursor query(ContentResolver cr,
    765                 String[] projection, String where, String orderBy) {
    766             return cr.query(CONTENT_URI, projection, where,
    767                     null, orderBy == null ? null : orderBy);
    768         }
    769 
    770         public static final String getRosterEtag(ContentResolver resolver, long accountId) {
    771             String retVal = null;
    772 
    773             Cursor c = resolver.query(CONTENT_URI,
    774                     CONTACT_ETAG_PROJECTION,
    775                     ACCOUNT + "=" + accountId,
    776                     null /* selection args */,
    777                     null /* sort order */);
    778 
    779             try {
    780                 if (c.moveToFirst()) {
    781                     retVal = c.getString(COLUMN_ETAG);
    782                 }
    783             } finally {
    784                 c.close();
    785             }
    786 
    787             return retVal;
    788         }
    789 
    790         public static final String getOtrEtag(ContentResolver resolver, long accountId) {
    791             String retVal = null;
    792 
    793             Cursor c = resolver.query(CONTENT_URI,
    794                     CONTACT_OTR_ETAG_PROJECTION,
    795                     ACCOUNT + "=" + accountId,
    796                     null /* selection args */,
    797                     null /* sort order */);
    798 
    799             try {
    800                 if (c.moveToFirst()) {
    801                     retVal = c.getString(COLUMN_OTR_ETAG);
    802                 }
    803             } finally {
    804                 c.close();
    805             }
    806 
    807             return retVal;
    808         }
    809 
    810         private static final String[] CONTACT_ETAG_PROJECTION = new String[] {
    811                 Imps.ContactsEtag.ETAG    // 0
    812         };
    813 
    814         private static int COLUMN_ETAG = 0;
    815 
    816         private static final String[] CONTACT_OTR_ETAG_PROJECTION = new String[] {
    817                 Imps.ContactsEtag.OTR_ETAG    // 0
    818         };
    819 
    820         private static int COLUMN_OTR_ETAG = 0;
    821 
    822         /**
    823          * The content:// style URL for this table
    824          */
    825         public static final Uri CONTENT_URI =
    826             Uri.parse("content://imps/contactsEtag");
    827 
    828         /**
    829          * The MIME type of {@link #CONTENT_URI} providing a directory of
    830          * people.
    831          */
    832         public static final String CONTENT_TYPE =
    833                 "vnd.android.cursor.dir/imps-contactsEtag";
    834 
    835         /**
    836          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
    837          * person.
    838          */
    839         public static final String CONTENT_ITEM_TYPE =
    840                 "vnd.android.cursor.item/imps-contactsEtag";
    841     }
    842 
    843     /**
    844      * Message type definition
    845      */
    846     public interface MessageType {
    847         /* sent message */
    848         int OUTGOING = 0;
    849         /* received message */
    850         int INCOMING = 1;
    851         /* presence became available */
    852         int PRESENCE_AVAILABLE = 2;
    853         /* presence became away */
    854         int PRESENCE_AWAY = 3;
    855         /* presence became DND (busy) */
    856         int PRESENCE_DND = 4;
    857         /* presence became unavailable */
    858         int PRESENCE_UNAVAILABLE = 5;
    859         /* the message is converted to a group chat */
    860         int CONVERT_TO_GROUPCHAT = 6;
    861         /* generic status */
    862         int STATUS = 7;
    863         /* the message cannot be sent now, but will be sent later */
    864         int POSTPONED = 8;
    865         /* off The Record status is turned off */
    866         int OTR_IS_TURNED_OFF = 9;
    867         /* off the record status is turned on */
    868         int OTR_IS_TURNED_ON = 10;
    869         /* off the record status turned on by user */
    870         int OTR_TURNED_ON_BY_USER = 11;
    871         /* off the record status turned on by buddy */
    872         int OTR_TURNED_ON_BY_BUDDY = 12;
    873     }
    874 
    875     /**
    876      * The common columns for messages table
    877      */
    878     public interface MessageColumns {
    879         /**
    880          * The thread_id column stores the contact id of the contact the message belongs to.
    881          * For groupchat messages, the thread_id stores the group id, which is the contact id
    882          * of the temporary group contact created for the groupchat. So there should be no
    883          * collision between groupchat message thread id and regular message thread id.
    884          */
    885         String THREAD_ID = "thread_id";
    886 
    887         /**
    888          * The nickname. This is used for groupchat messages to indicate the participant's
    889          * nickname. For non groupchat messages, this field should be left empty.
    890          */
    891         String NICKNAME = "nickname";
    892 
    893         /**
    894          * The body
    895          * <P>Type: TEXT</P>
    896          */
    897         String BODY = "body";
    898 
    899         /**
    900          * The date this message is sent or received
    901          * <P>Type: INTEGER</P>
    902          */
    903         String DATE = "date";
    904 
    905         /**
    906          * Message Type, see {@link MessageType}
    907          * <P>Type: INTEGER</P>
    908          */
    909         String TYPE = "type";
    910 
    911         /**
    912          * Error Code: 0 means no error.
    913          * <P>Type: INTEGER </P>
    914          */
    915         String ERROR_CODE = "err_code";
    916 
    917         /**
    918          * Error Message
    919          * <P>Type: TEXT</P>
    920          */
    921         String ERROR_MESSAGE = "err_msg";
    922 
    923         /**
    924          * Packet ID, auto assigned by the GTalkService for outgoing messages or the
    925          * GTalk server for incoming messages. The packet id field is optional for messages,
    926          * so it could be null.
    927          * <P>Type: STRING</P>
    928          */
    929         String PACKET_ID = "packet_id";
    930 
    931         /**
    932          * Is groupchat message or not
    933          * <P>Type: INTEGER</P>
    934          */
    935         String IS_GROUP_CHAT = "is_muc";
    936 
    937         /**
    938          * A hint that the UI should show the sent time of this message
    939          * <P>Type: INTEGER</P>
    940          */
    941         String DISPLAY_SENT_TIME = "show_ts";
    942     }
    943 
    944     /**
    945      * This table contains messages.
    946      */
    947     public static final class Messages implements BaseColumns, MessageColumns {
    948         /**
    949          * no public constructor since this is a utility class
    950          */
    951         private Messages() {}
    952 
    953         /**
    954          * Gets the Uri to query messages by thread id.
    955          *
    956          * @param threadId the thread id of the message.
    957          * @return the Uri
    958          */
    959         public static final Uri getContentUriByThreadId(long threadId) {
    960             Uri.Builder builder = CONTENT_URI_MESSAGES_BY_THREAD_ID.buildUpon();
    961             ContentUris.appendId(builder, threadId);
    962             return builder.build();
    963         }
    964 
    965         /**
    966          * @deprecated
    967          *
    968          * Gets the Uri to query messages by account and contact.
    969          *
    970          * @param accountId the account id of the contact.
    971          * @param username the user name of the contact.
    972          * @return the Uri
    973          */
    974         public static final Uri getContentUriByContact(long accountId, String username) {
    975             Uri.Builder builder = CONTENT_URI_MESSAGES_BY_ACCOUNT_AND_CONTACT.buildUpon();
    976             ContentUris.appendId(builder, accountId);
    977             builder.appendPath(username);
    978             return builder.build();
    979         }
    980 
    981         /**
    982          * Gets the Uri to query messages by provider.
    983          *
    984          * @param providerId the service provider id.
    985          * @return the Uri
    986          */
    987         public static final Uri getContentUriByProvider(long providerId) {
    988             Uri.Builder builder = CONTENT_URI_MESSAGES_BY_PROVIDER.buildUpon();
    989             ContentUris.appendId(builder, providerId);
    990             return builder.build();
    991         }
    992 
    993         /**
    994          * Gets the Uri to query off the record messages by account.
    995          *
    996          * @param accountId the account id.
    997          * @return the Uri
    998          */
    999         public static final Uri getContentUriByAccount(long accountId) {
   1000             Uri.Builder builder = CONTENT_URI_BY_ACCOUNT.buildUpon();
   1001             ContentUris.appendId(builder, accountId);
   1002             return builder.build();
   1003         }
   1004 
   1005         /**
   1006          * Gets the Uri to query off the record messages by thread id.
   1007          *
   1008          * @param threadId the thread id of the message.
   1009          * @return the Uri
   1010          */
   1011         public static final Uri getOtrMessagesContentUriByThreadId(long threadId) {
   1012             Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID.buildUpon();
   1013             ContentUris.appendId(builder, threadId);
   1014             return builder.build();
   1015         }
   1016 
   1017         /**
   1018          * @deprecated
   1019          *
   1020          * Gets the Uri to query off the record messages by account and contact.
   1021          *
   1022          * @param accountId the account id of the contact.
   1023          * @param username the user name of the contact.
   1024          * @return the Uri
   1025          */
   1026         public static final Uri getOtrMessagesContentUriByContact(long accountId, String username) {
   1027             Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT.buildUpon();
   1028             ContentUris.appendId(builder, accountId);
   1029             builder.appendPath(username);
   1030             return builder.build();
   1031         }
   1032 
   1033         /**
   1034          * Gets the Uri to query off the record messages by provider.
   1035          *
   1036          * @param providerId the service provider id.
   1037          * @return the Uri
   1038          */
   1039         public static final Uri getOtrMessagesContentUriByProvider(long providerId) {
   1040             Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_PROVIDER.buildUpon();
   1041             ContentUris.appendId(builder, providerId);
   1042             return builder.build();
   1043         }
   1044 
   1045         /**
   1046          * Gets the Uri to query off the record messages by account.
   1047          *
   1048          * @param accountId the account id.
   1049          * @return the Uri
   1050          */
   1051         public static final Uri getOtrMessagesContentUriByAccount(long accountId) {
   1052             Uri.Builder builder = OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT.buildUpon();
   1053             ContentUris.appendId(builder, accountId);
   1054             return builder.build();
   1055         }
   1056 
   1057         /**
   1058          * The content:// style URL for this table
   1059          */
   1060         public static final Uri CONTENT_URI =
   1061                 Uri.parse("content://imps/messages");
   1062 
   1063         /**
   1064          * The content:// style URL for messages by thread id
   1065          */
   1066         public static final Uri CONTENT_URI_MESSAGES_BY_THREAD_ID =
   1067                 Uri.parse("content://imps/messagesByThreadId");
   1068 
   1069         /**
   1070          * The content:// style URL for messages by account and contact
   1071          */
   1072         public static final Uri CONTENT_URI_MESSAGES_BY_ACCOUNT_AND_CONTACT =
   1073                 Uri.parse("content://imps/messagesByAcctAndContact");
   1074 
   1075         /**
   1076          * The content:// style URL for messages by provider
   1077          */
   1078         public static final Uri CONTENT_URI_MESSAGES_BY_PROVIDER =
   1079                 Uri.parse("content://imps/messagesByProvider");
   1080 
   1081         /**
   1082          * The content:// style URL for messages by account
   1083          */
   1084         public static final Uri CONTENT_URI_BY_ACCOUNT =
   1085                 Uri.parse("content://imps/messagesByAccount");
   1086 
   1087         /**
   1088          * The content:// style url for off the record messages
   1089          */
   1090         public static final Uri OTR_MESSAGES_CONTENT_URI =
   1091                 Uri.parse("content://imps/otrMessages");
   1092 
   1093         /**
   1094          * The content:// style url for off the record messages by thread id
   1095          */
   1096         public static final Uri OTR_MESSAGES_CONTENT_URI_BY_THREAD_ID =
   1097                 Uri.parse("content://imps/otrMessagesByThreadId");
   1098 
   1099         /**
   1100          * The content:// style url for off the record messages by account and contact
   1101          */
   1102         public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT_AND_CONTACT =
   1103                 Uri.parse("content://imps/otrMessagesByAcctAndContact");
   1104 
   1105         /**
   1106          * The content:// style URL for off the record messages by provider
   1107          */
   1108         public static final Uri OTR_MESSAGES_CONTENT_URI_BY_PROVIDER =
   1109                 Uri.parse("content://imps/otrMessagesByProvider");
   1110 
   1111         /**
   1112          * The content:// style URL for off the record messages by account
   1113          */
   1114         public static final Uri OTR_MESSAGES_CONTENT_URI_BY_ACCOUNT =
   1115                 Uri.parse("content://imps/otrMessagesByAccount");
   1116 
   1117         /**
   1118          * The MIME type of {@link #CONTENT_URI} providing a directory of
   1119          * people.
   1120          */
   1121         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-messages";
   1122 
   1123         /**
   1124          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
   1125          * person.
   1126          */
   1127         public static final String CONTENT_ITEM_TYPE =
   1128                 "vnd.android.cursor.item/imps-messages";
   1129 
   1130         /**
   1131          * The default sort order for this table
   1132          */
   1133         public static final String DEFAULT_SORT_ORDER = "date ASC";
   1134 
   1135         /**
   1136          * The "contact" column. This is not a real column in the messages table, but a
   1137          * temoprary column created when querying for messages (joined with the contacts table)
   1138          */
   1139         public static final String CONTACT = "contact";
   1140     }
   1141 
   1142     /**
   1143      * Columns for the GroupMember table.
   1144      */
   1145     public interface GroupMemberColumns {
   1146         /**
   1147          * The id of the group this member belongs to.
   1148          * <p>Type: INTEGER</p>
   1149          */
   1150         String GROUP = "groupId";
   1151 
   1152         /**
   1153          * The full name of this member.
   1154          * <p>Type: TEXT</p>
   1155          */
   1156         String USERNAME = "username";
   1157 
   1158         /**
   1159          * The nick name of this member.
   1160          * <p>Type: TEXT</p>
   1161          */
   1162         String NICKNAME = "nickname";
   1163     }
   1164 
   1165     public final static class GroupMembers implements GroupMemberColumns {
   1166         private GroupMembers(){}
   1167 
   1168         public static final Uri CONTENT_URI =
   1169             Uri.parse("content://imps/groupMembers");
   1170 
   1171         /**
   1172          * The MIME type of {@link #CONTENT_URI} providing a directory of
   1173          * group members.
   1174          */
   1175         public static final String CONTENT_TYPE =
   1176             "vnd.android.cursor.dir/imps-groupMembers";
   1177 
   1178         /**
   1179          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
   1180          * group member.
   1181          */
   1182         public static final String CONTENT_ITEM_TYPE =
   1183                 "vnd.android.cursor.item/imps-groupMembers";
   1184     }
   1185 
   1186     /**
   1187      * Columns from the Invitation table.
   1188      */
   1189     public interface InvitationColumns {
   1190         /**
   1191          * The provider id.
   1192          * <p>Type: INTEGER</p>
   1193          */
   1194         String PROVIDER = "providerId";
   1195 
   1196         /**
   1197          * The account id.
   1198          * <p>Type: INTEGER</p>
   1199          */
   1200         String ACCOUNT = "accountId";
   1201 
   1202         /**
   1203          * The invitation id.
   1204          * <p>Type: TEXT</p>
   1205          */
   1206         String INVITE_ID = "inviteId";
   1207 
   1208         /**
   1209          * The name of the sender of the invitation.
   1210          * <p>Type: TEXT</p>
   1211          */
   1212         String SENDER = "sender";
   1213 
   1214         /**
   1215          * The name of the group which the sender invite you to join.
   1216          * <p>Type: TEXT</p>
   1217          */
   1218         String GROUP_NAME = "groupName";
   1219 
   1220         /**
   1221          * A note
   1222          * <p>Type: TEXT</p>
   1223          */
   1224         String NOTE = "note";
   1225 
   1226         /**
   1227          * The current status of the invitation.
   1228          * <p>Type: TEXT</p>
   1229          */
   1230         String STATUS = "status";
   1231 
   1232         int STATUS_PENDING = 0;
   1233         int STATUS_ACCEPTED = 1;
   1234         int STATUS_REJECTED = 2;
   1235     }
   1236 
   1237     /**
   1238      * This table contains the invitations received from others.
   1239      */
   1240     public final static class Invitation implements InvitationColumns,
   1241             BaseColumns {
   1242         private Invitation() {
   1243         }
   1244 
   1245         /**
   1246          * The content:// style URL for this table
   1247          */
   1248         public static final Uri CONTENT_URI =
   1249             Uri.parse("content://imps/invitations");
   1250 
   1251         /**
   1252          * The MIME type of {@link #CONTENT_URI} providing a directory of
   1253          * invitations.
   1254          */
   1255         public static final String CONTENT_TYPE =
   1256             "vnd.android.cursor.dir/imps-invitations";
   1257 
   1258         /**
   1259          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
   1260          * invitation.
   1261          */
   1262         public static final String CONTENT_ITEM_TYPE =
   1263                 "vnd.android.cursor.item/imps-invitations";
   1264     }
   1265 
   1266     /**
   1267      * Columns from the Avatars table
   1268      */
   1269     public interface AvatarsColumns {
   1270         /**
   1271          * The contact this avatar belongs to
   1272          * <P>Type: TEXT</P>
   1273          */
   1274         String CONTACT = "contact";
   1275 
   1276         String PROVIDER = "provider_id";
   1277 
   1278         String ACCOUNT = "account_id";
   1279 
   1280         /**
   1281          * The hash of the image data
   1282          * <P>Type: TEXT</P>
   1283          */
   1284         String HASH = "hash";
   1285 
   1286         /**
   1287          * raw image data
   1288          * <P>Type: BLOB</P>
   1289          */
   1290         String DATA = "data";
   1291     }
   1292 
   1293     /**
   1294      * This table contains avatars.
   1295      */
   1296     public static final class Avatars implements BaseColumns, AvatarsColumns {
   1297         /**
   1298          * no public constructor since this is a utility class
   1299          */
   1300         private Avatars() {}
   1301 
   1302         /**
   1303          * The content:// style URL for this table
   1304          */
   1305         public static final Uri CONTENT_URI = Uri.parse("content://imps/avatars");
   1306 
   1307         /**
   1308          * The content:// style URL for avatars by provider, account and contact
   1309          */
   1310         public static final Uri CONTENT_URI_AVATARS_BY =
   1311                 Uri.parse("content://imps/avatarsBy");
   1312 
   1313         /**
   1314          * The MIME type of {@link #CONTENT_URI} providing the avatars
   1315          */
   1316         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-avatars";
   1317 
   1318         /**
   1319          * The MIME type of a {@link #CONTENT_URI}
   1320          */
   1321         public static final String CONTENT_ITEM_TYPE =
   1322                 "vnd.android.cursor.item/imps-avatars";
   1323 
   1324         /**
   1325          * The default sort order for this table
   1326          */
   1327         public static final String DEFAULT_SORT_ORDER = "contact ASC";
   1328 
   1329     }
   1330 
   1331     /**
   1332      * Common presence columns shared between the IM and contacts presence tables
   1333      */
   1334     public interface CommonPresenceColumns {
   1335         /**
   1336          * The priority, an integer, used by XMPP presence
   1337          * <P>Type: INTEGER</P>
   1338          */
   1339         String PRIORITY = "priority";
   1340 
   1341         /**
   1342          * The server defined status.
   1343          * <P>Type: INTEGER (one of the values below)</P>
   1344          */
   1345         String PRESENCE_STATUS = "mode";
   1346 
   1347         /**
   1348          * Presence Status definition
   1349          */
   1350         int OFFLINE = 0;
   1351         int INVISIBLE = 1;
   1352         int AWAY = 2;
   1353         int IDLE = 3;
   1354         int DO_NOT_DISTURB = 4;
   1355         int AVAILABLE = 5;
   1356 
   1357         /**
   1358          * The user defined status line.
   1359          * <P>Type: TEXT</P>
   1360          */
   1361         String PRESENCE_CUSTOM_STATUS = "status";
   1362     }
   1363 
   1364     /**
   1365      * Columns from the Presence table.
   1366      */
   1367     public interface PresenceColumns extends CommonPresenceColumns {
   1368         /**
   1369          * The contact id
   1370          * <P>Type: INTEGER</P>
   1371          */
   1372         String CONTACT_ID = "contact_id";
   1373 
   1374         /**
   1375          * The contact's JID resource, only relevant for XMPP contact
   1376          * <P>Type: TEXT</P>
   1377          */
   1378         String JID_RESOURCE = "jid_resource";
   1379 
   1380         /**
   1381          * The contact's client type
   1382          */
   1383         String CLIENT_TYPE = "client_type";
   1384 
   1385         /**
   1386          * client type definitions
   1387          */
   1388         int CLIENT_TYPE_DEFAULT = 0;
   1389         int CLIENT_TYPE_MOBILE = 1;
   1390         int CLIENT_TYPE_ANDROID = 2;
   1391     }
   1392 
   1393     /**
   1394      * Contains presence infomation for contacts.
   1395      */
   1396     public static final class Presence implements BaseColumns, PresenceColumns {
   1397         /**
   1398          * The content:// style URL for this table
   1399          */
   1400         public static final Uri CONTENT_URI = Uri.parse("content://imps/presence");
   1401 
   1402         /**
   1403          * The content URL for IM presences for an account
   1404          */
   1405         public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://imps/presence/account");
   1406 
   1407         /**
   1408          * The content:// style URL for operations on bulk contacts
   1409          */
   1410         public static final Uri BULK_CONTENT_URI = Uri.parse("content://imps/bulk_presence");
   1411 
   1412         /**
   1413          * The content:// style URL for seeding presences for a given account id.
   1414          */
   1415         public static final Uri SEED_PRESENCE_BY_ACCOUNT_CONTENT_URI =
   1416                 Uri.parse("content://imps/seed_presence/account");
   1417 
   1418         /**
   1419          * The MIME type of a {@link #CONTENT_URI} providing a directory of presence
   1420          */
   1421         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-presence";
   1422 
   1423         /**
   1424          * The default sort order for this table
   1425          */
   1426         public static final String DEFAULT_SORT_ORDER = "mode DESC";
   1427     }
   1428 
   1429     /**
   1430      * Columns from the Chats table.
   1431      */
   1432     public interface ChatsColumns {
   1433         /**
   1434          * The contact ID this chat belongs to. The value is a long.
   1435          * <P>Type: INT</P>
   1436          */
   1437         String CONTACT_ID = "contact_id";
   1438 
   1439         /**
   1440          * The GTalk JID resource. The value is a string.
   1441          * <P>Type: TEXT</P>
   1442          */
   1443         String JID_RESOURCE = "jid_resource";
   1444 
   1445         /**
   1446          * Whether this is a groupchat or not.
   1447          * <P>Type: INT</P>
   1448          */
   1449         String GROUP_CHAT = "groupchat";
   1450 
   1451         /**
   1452          * The last unread message. This both indicates that there is an
   1453          * unread message, and what the message is.
   1454          * <P>Type: TEXT</P>
   1455          */
   1456         String LAST_UNREAD_MESSAGE = "last_unread_message";
   1457 
   1458         /**
   1459          * The last message timestamp
   1460          * <P>Type: INT</P>
   1461          */
   1462         String LAST_MESSAGE_DATE = "last_message_date";
   1463 
   1464         /**
   1465          * A message that is being composed.  This indicates that there was a
   1466          * message being composed when the chat screen was shutdown, and what the
   1467          * message is.
   1468          * <P>Type: TEXT</P>
   1469          */
   1470         String UNSENT_COMPOSED_MESSAGE = "unsent_composed_message";
   1471 
   1472         /**
   1473          * A value from 0-9 indicating which quick-switch chat screen slot this
   1474          * chat is occupying.  If none (for instance, this is the 12th active chat)
   1475          * then the value is -1.
   1476          * <P>Type: INT</P>
   1477          */
   1478         String SHORTCUT = "shortcut";
   1479     }
   1480 
   1481     /**
   1482      * Contains ongoing chat sessions.
   1483      */
   1484     public static final class Chats implements BaseColumns, ChatsColumns {
   1485         /**
   1486          * no public constructor since this is a utility class
   1487          */
   1488         private Chats() {}
   1489 
   1490         /**
   1491          * The content:// style URL for this table
   1492          */
   1493         public static final Uri CONTENT_URI =
   1494             Uri.parse("content://imps/chats");
   1495 
   1496         /**
   1497          * The content URL for all chats that belong to the account
   1498          */
   1499         public static final Uri CONTENT_URI_BY_ACCOUNT = Uri.parse("content://imps/chats/account");
   1500 
   1501         /**
   1502          * The MIME type of {@link #CONTENT_URI} providing a directory of chats.
   1503          */
   1504         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/imps-chats";
   1505 
   1506         /**
   1507          * The MIME type of a {@link #CONTENT_URI} subdirectory of a single chat.
   1508          */
   1509         public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/imps-chats";
   1510 
   1511         /**
   1512          * The default sort order for this table
   1513          */
   1514         public static final String DEFAULT_SORT_ORDER = "last_message_date ASC";
   1515     }
   1516 
   1517     /**
   1518      * Columns from session cookies table. Used for IMPS.
   1519      */
   1520     public static interface SessionCookiesColumns {
   1521         String NAME = "name";
   1522         String VALUE = "value";
   1523         String PROVIDER = "provider";
   1524         String ACCOUNT = "account";
   1525     }
   1526 
   1527     /**
   1528      * Contains IMPS session cookies.
   1529      */
   1530     public static class SessionCookies implements SessionCookiesColumns, BaseColumns {
   1531         private SessionCookies() {
   1532         }
   1533 
   1534         /**
   1535          * The content:// style URI for this table
   1536          */
   1537         public static final Uri CONTENT_URI = Uri.parse("content://imps/sessionCookies");
   1538 
   1539         /**
   1540          * The content:// style URL for session cookies by provider and account
   1541          */
   1542         public static final Uri CONTENT_URI_SESSION_COOKIES_BY =
   1543             Uri.parse("content://imps/sessionCookiesBy");
   1544 
   1545         /**
   1546          * The MIME type of {@link #CONTENT_URI} providing a directory of
   1547          * people.
   1548          */
   1549         public static final String CONTENT_TYPE = "vnd.android-dir/imps-sessionCookies";
   1550     }
   1551 
   1552     /**
   1553      * Columns from ProviderSettings table
   1554      */
   1555     public static interface ProviderSettingsColumns {
   1556          /**
   1557           * The id in database of the related provider
   1558           *
   1559           * <P>Type: INT</P>
   1560           */
   1561         String PROVIDER = "provider";
   1562 
   1563         /**
   1564          * The name of the setting
   1565          * <P>Type: TEXT</P>
   1566          */
   1567         String NAME = "name";
   1568 
   1569         /**
   1570          * The value of the setting
   1571          * <P>Type: TEXT</P>
   1572          */
   1573         String VALUE = "value";
   1574     }
   1575 
   1576     public static class ProviderSettings implements ProviderSettingsColumns {
   1577         private ProviderSettings() {
   1578         }
   1579 
   1580         /**
   1581          * The content:// style URI for this table
   1582          */
   1583         public static final Uri CONTENT_URI =
   1584                 Uri.parse("content://imps/providerSettings");
   1585 
   1586         /**
   1587          * The MIME type of {@link #CONTENT_URI} providing provider settings
   1588          */
   1589         public static final String CONTENT_TYPE = "vnd.android-dir/imps-providerSettings";
   1590 
   1591         /**
   1592          * A boolean value to indicate whether this provider should show the offline contacts
   1593          */
   1594         public static final String SHOW_OFFLINE_CONTACTS = "show_offline_contacts";
   1595 
   1596         /** controls whether or not the GTalk service automatically connect to server. */
   1597         public static final String SETTING_AUTOMATICALLY_CONNECT_GTALK = "gtalk_auto_connect";
   1598 
   1599         /** controls whether or not the IM service will be automatically started after boot */
   1600         public static final String SETTING_AUTOMATICALLY_START_SERVICE = "auto_start_service";
   1601 
   1602         /** controls whether or not the offline contacts will be hided */
   1603         public static final String SETTING_HIDE_OFFLINE_CONTACTS = "hide_offline_contacts";
   1604 
   1605         /** controls whether or not enable the IM notification */
   1606         public static final String SETTING_ENABLE_NOTIFICATION = "enable_notification";
   1607 
   1608         /** specifies whether or not to vibrate */
   1609         public static final String SETTING_VIBRATE = "vibrate";
   1610 
   1611         /** specifies the Uri string of the ringtone */
   1612         public static final String SETTING_RINGTONE = "ringtone";
   1613 
   1614         /** specifies the Uri of the default ringtone */
   1615         public static final String SETTING_RINGTONE_DEFAULT =
   1616                 "content://settings/system/notification_sound";
   1617 
   1618         /** specifies whether or not to show mobile indicator to friends */
   1619         public static final String SETTING_SHOW_MOBILE_INDICATOR = "mobile_indicator";
   1620 
   1621         /** specifies whether or not to show as away when device is idle */
   1622         public static final String SETTING_SHOW_AWAY_ON_IDLE = "show_away_on_idle";
   1623 
   1624         /** specifies whether or not to upload heartbeat stat upon login */
   1625         public static final String SETTING_UPLOAD_HEARTBEAT_STAT = "upload_heartbeat_stat";
   1626 
   1627         /** specifies the last heartbeat interval received from the server */
   1628         public static final String SETTING_HEARTBEAT_INTERVAL = "heartbeat_interval";
   1629 
   1630         /** specifiy the JID resource used for Google Talk connection */
   1631         public static final String SETTING_JID_RESOURCE = "jid_resource";
   1632 
   1633         /**
   1634          * Used for reliable message queue (RMQ). This is for storing the last rmq id received
   1635          * from the GTalk server
   1636          */
   1637         public static final String LAST_RMQ_RECEIVED = "last_rmq_rec";
   1638 
   1639         /**
   1640          * Query the settings of the provider specified by id
   1641          *
   1642          * @param cr
   1643          *            the relative content resolver
   1644          * @param providerId
   1645          *            the specified id of provider
   1646          * @return a HashMap which contains all the settings for the specified
   1647          *         provider
   1648          */
   1649         public static HashMap<String, String> queryProviderSettings(ContentResolver cr,
   1650                 long providerId) {
   1651             HashMap<String, String> settings = new HashMap<String, String>();
   1652 
   1653             String[] projection = { NAME, VALUE };
   1654             Cursor c = cr.query(ContentUris.withAppendedId(CONTENT_URI, providerId), projection, null, null, null);
   1655             if (c == null) {
   1656                 return null;
   1657             }
   1658 
   1659             while(c.moveToNext()) {
   1660                 settings.put(c.getString(0), c.getString(1));
   1661             }
   1662 
   1663             c.close();
   1664 
   1665             return settings;
   1666         }
   1667 
   1668         /**
   1669          * Get the string value of setting which is specified by provider id and the setting name.
   1670          *
   1671          * @param cr The ContentResolver to use to access the settings table.
   1672          * @param providerId The id of the provider.
   1673          * @param settingName The name of the setting.
   1674          * @return The value of the setting if the setting exist, otherwise return null.
   1675          */
   1676         public static String getStringValue(ContentResolver cr, long providerId, String settingName) {
   1677             String ret = null;
   1678             Cursor c = getSettingValue(cr, providerId, settingName);
   1679             if (c != null) {
   1680                 ret = c.getString(0);
   1681                 c.close();
   1682             }
   1683 
   1684             return ret;
   1685         }
   1686 
   1687         /**
   1688          * Get the boolean value of setting which is specified by provider id and the setting name.
   1689          *
   1690          * @param cr The ContentResolver to use to access the settings table.
   1691          * @param providerId The id of the provider.
   1692          * @param settingName The name of the setting.
   1693          * @return The value of the setting if the setting exist, otherwise return false.
   1694          */
   1695         public static boolean getBooleanValue(ContentResolver cr, long providerId, String settingName) {
   1696             boolean ret = false;
   1697             Cursor c = getSettingValue(cr, providerId, settingName);
   1698             if (c != null) {
   1699                 ret = c.getInt(0) != 0;
   1700                 c.close();
   1701             }
   1702             return ret;
   1703         }
   1704 
   1705         private static Cursor getSettingValue(ContentResolver cr, long providerId, String settingName) {
   1706             Cursor c = cr.query(ContentUris.withAppendedId(CONTENT_URI, providerId), new String[]{VALUE}, NAME + "=?",
   1707                     new String[]{settingName}, null);
   1708             if (c != null) {
   1709                 if (!c.moveToFirst()) {
   1710                     c.close();
   1711                     return null;
   1712                 }
   1713             }
   1714             return c;
   1715         }
   1716 
   1717         /**
   1718          * Save a long value of setting in the table providerSetting.
   1719          *
   1720          * @param cr The ContentProvider used to access the providerSetting table.
   1721          * @param providerId The id of the provider.
   1722          * @param name The name of the setting.
   1723          * @param value The value of the setting.
   1724          */
   1725         public static void putLongValue(ContentResolver cr, long providerId, String name,
   1726                 long value) {
   1727             ContentValues v = new ContentValues(3);
   1728             v.put(PROVIDER, providerId);
   1729             v.put(NAME, name);
   1730             v.put(VALUE, value);
   1731 
   1732             cr.insert(CONTENT_URI, v);
   1733         }
   1734 
   1735         /**
   1736          * Save a boolean value of setting in the table providerSetting.
   1737          *
   1738          * @param cr The ContentProvider used to access the providerSetting table.
   1739          * @param providerId The id of the provider.
   1740          * @param name The name of the setting.
   1741          * @param value The value of the setting.
   1742          */
   1743         public static void putBooleanValue(ContentResolver cr, long providerId, String name,
   1744                 boolean value) {
   1745             ContentValues v = new ContentValues(3);
   1746             v.put(PROVIDER, providerId);
   1747             v.put(NAME, name);
   1748             v.put(VALUE, Boolean.toString(value));
   1749 
   1750             cr.insert(CONTENT_URI, v);
   1751         }
   1752 
   1753         /**
   1754          * Save a string value of setting in the table providerSetting.
   1755          *
   1756          * @param cr The ContentProvider used to access the providerSetting table.
   1757          * @param providerId The id of the provider.
   1758          * @param name The name of the setting.
   1759          * @param value The value of the setting.
   1760          */
   1761         public static void putStringValue(ContentResolver cr, long providerId, String name,
   1762                 String value) {
   1763             ContentValues v = new ContentValues(3);
   1764             v.put(PROVIDER, providerId);
   1765             v.put(NAME, name);
   1766             v.put(VALUE, value);
   1767 
   1768             cr.insert(CONTENT_URI, v);
   1769         }
   1770 
   1771         /**
   1772          * A convenience method to set whether or not the GTalk service should be started
   1773          * automatically.
   1774          *
   1775          * @param contentResolver The ContentResolver to use to access the settings table
   1776          * @param autoConnect Whether the GTalk service should be started automatically.
   1777          */
   1778         public static void setAutomaticallyConnectGTalk(ContentResolver contentResolver,
   1779                 long providerId, boolean autoConnect) {
   1780             putBooleanValue(contentResolver, providerId, SETTING_AUTOMATICALLY_CONNECT_GTALK,
   1781                     autoConnect);
   1782         }
   1783 
   1784         /**
   1785          * A convenience method to set whether or not the offline contacts should be hided
   1786          *
   1787          * @param contentResolver The ContentResolver to use to access the setting table
   1788          * @param hideOfflineContacts Whether the offline contacts should be hided
   1789          */
   1790         public static void setHideOfflineContacts(ContentResolver contentResolver,
   1791                 long providerId, boolean hideOfflineContacts) {
   1792             putBooleanValue(contentResolver, providerId, SETTING_HIDE_OFFLINE_CONTACTS,
   1793                     hideOfflineContacts);
   1794         }
   1795 
   1796         /**
   1797          * A convenience method to set whether or not enable the IM notification.
   1798          *
   1799          * @param contentResolver The ContentResolver to use to access the setting table.
   1800          * @param enable Whether enable the IM notification
   1801          */
   1802         public static void setEnableNotification(ContentResolver contentResolver, long providerId,
   1803                 boolean enable) {
   1804             putBooleanValue(contentResolver, providerId, SETTING_ENABLE_NOTIFICATION, enable);
   1805         }
   1806 
   1807         /**
   1808          * A convenience method to set whether or not to vibrate.
   1809          *
   1810          * @param contentResolver The ContentResolver to use to access the setting table.
   1811          * @param vibrate Whether or not to vibrate
   1812          */
   1813         public static void setVibrate(ContentResolver contentResolver, long providerId,
   1814                 boolean vibrate) {
   1815             putBooleanValue(contentResolver, providerId, SETTING_VIBRATE, vibrate);
   1816         }
   1817 
   1818         /**
   1819          * A convenience method to set the Uri String of the ringtone.
   1820          *
   1821          * @param contentResolver The ContentResolver to use to access the setting table.
   1822          * @param ringtoneUri The Uri String of the ringtone to be set.
   1823          */
   1824         public static void setRingtoneURI(ContentResolver contentResolver, long providerId,
   1825                 String ringtoneUri) {
   1826             putStringValue(contentResolver, providerId, SETTING_RINGTONE, ringtoneUri);
   1827         }
   1828 
   1829         /**
   1830          * A convenience method to set whether or not to show mobile indicator.
   1831          *
   1832          * @param contentResolver The ContentResolver to use to access the setting table.
   1833          * @param showMobileIndicator Whether or not to show mobile indicator.
   1834          */
   1835         public static void setShowMobileIndicator(ContentResolver contentResolver, long providerId,
   1836                 boolean showMobileIndicator) {
   1837             putBooleanValue(contentResolver, providerId, SETTING_SHOW_MOBILE_INDICATOR,
   1838                     showMobileIndicator);
   1839         }
   1840 
   1841         /**
   1842          * A convenience method to set whether or not to show as away when device is idle.
   1843          *
   1844          * @param contentResolver The ContentResolver to use to access the setting table.
   1845          * @param showAway Whether or not to show as away when device is idle.
   1846          */
   1847         public static void setShowAwayOnIdle(ContentResolver contentResolver,
   1848                 long providerId, boolean showAway) {
   1849             putBooleanValue(contentResolver, providerId, SETTING_SHOW_AWAY_ON_IDLE, showAway);
   1850         }
   1851 
   1852         /**
   1853          * A convenience method to set whether or not to upload heartbeat stat.
   1854          *
   1855          * @param contentResolver The ContentResolver to use to access the setting table.
   1856          * @param uploadStat Whether or not to upload heartbeat stat.
   1857          */
   1858         public static void setUploadHeartbeatStat(ContentResolver contentResolver,
   1859                 long providerId, boolean uploadStat) {
   1860             putBooleanValue(contentResolver, providerId, SETTING_UPLOAD_HEARTBEAT_STAT, uploadStat);
   1861         }
   1862 
   1863         /**
   1864          * A convenience method to set the heartbeat interval last received from the server.
   1865          *
   1866          * @param contentResolver The ContentResolver to use to access the setting table.
   1867          * @param interval The heartbeat interval last received from the server.
   1868          */
   1869         public static void setHeartbeatInterval(ContentResolver contentResolver,
   1870                 long providerId, long interval) {
   1871             putLongValue(contentResolver, providerId, SETTING_HEARTBEAT_INTERVAL, interval);
   1872         }
   1873 
   1874         /**
   1875          * A convenience method to set the jid resource.
   1876          */
   1877         public static void setJidResource(ContentResolver contentResolver,
   1878                                           long providerId, String jidResource) {
   1879             putStringValue(contentResolver, providerId, SETTING_JID_RESOURCE, jidResource);
   1880         }
   1881 
   1882         public static class QueryMap extends ContentQueryMap {
   1883             private ContentResolver mContentResolver;
   1884             private long mProviderId;
   1885 
   1886             public QueryMap(ContentResolver contentResolver, long providerId, boolean keepUpdated,
   1887                     Handler handlerForUpdateNotifications) {
   1888                 super(contentResolver.query(CONTENT_URI,
   1889                             new String[] {NAME,VALUE},
   1890                             PROVIDER + "=" + providerId,
   1891                             null, // no selection args
   1892                             null), // no sort order
   1893                         NAME, keepUpdated, handlerForUpdateNotifications);
   1894                 mContentResolver = contentResolver;
   1895                 mProviderId = providerId;
   1896             }
   1897 
   1898             /**
   1899              * Set if the GTalk service should automatically connect to server.
   1900              *
   1901              * @param autoConnect if the GTalk service should auto connect to server.
   1902              */
   1903             public void setAutomaticallyConnectToGTalkServer(boolean autoConnect) {
   1904                 ProviderSettings.setAutomaticallyConnectGTalk(mContentResolver, mProviderId,
   1905                         autoConnect);
   1906             }
   1907 
   1908             /**
   1909              * Check if the GTalk service should automatically connect to server.
   1910              * @return if the GTalk service should automatically connect to server.
   1911              */
   1912             public boolean getAutomaticallyConnectToGTalkServer() {
   1913                 return getBoolean(SETTING_AUTOMATICALLY_CONNECT_GTALK,
   1914                         true /* default to automatically sign in */);
   1915             }
   1916 
   1917             /**
   1918              * Set whether or not the offline contacts should be hided.
   1919              *
   1920              * @param hideOfflineContacts Whether or not the offline contacts should be hided.
   1921              */
   1922             public void setHideOfflineContacts(boolean hideOfflineContacts) {
   1923                 ProviderSettings.setHideOfflineContacts(mContentResolver, mProviderId,
   1924                         hideOfflineContacts);
   1925             }
   1926 
   1927             /**
   1928              * Check if the offline contacts should be hided.
   1929              *
   1930              * @return Whether or not the offline contacts should be hided.
   1931              */
   1932             public boolean getHideOfflineContacts() {
   1933                 return getBoolean(SETTING_HIDE_OFFLINE_CONTACTS,
   1934                         false/* by default not hide the offline contacts*/);
   1935             }
   1936 
   1937             /**
   1938              * Set whether or not enable the IM notification.
   1939              *
   1940              * @param enable Whether or not enable the IM notification.
   1941              */
   1942             public void setEnableNotification(boolean enable) {
   1943                 ProviderSettings.setEnableNotification(mContentResolver, mProviderId, enable);
   1944             }
   1945 
   1946             /**
   1947              * Check if the IM notification is enabled.
   1948              *
   1949              * @return Whether or not enable the IM notification.
   1950              */
   1951             public boolean getEnableNotification() {
   1952                 return getBoolean(SETTING_ENABLE_NOTIFICATION,
   1953                         true/* by default enable the notification */);
   1954             }
   1955 
   1956             /**
   1957              * Set whether or not to vibrate on IM notification.
   1958              *
   1959              * @param vibrate Whether or not to vibrate.
   1960              */
   1961             public void setVibrate(boolean vibrate) {
   1962                 ProviderSettings.setVibrate(mContentResolver, mProviderId, vibrate);
   1963             }
   1964 
   1965             /**
   1966              * Gets whether or not to vibrate on IM notification.
   1967              *
   1968              * @return Whether or not to vibrate.
   1969              */
   1970             public boolean getVibrate() {
   1971                 return getBoolean(SETTING_VIBRATE, false /* by default disable vibrate */);
   1972             }
   1973 
   1974             /**
   1975              * Set the Uri for the ringtone.
   1976              *
   1977              * @param ringtoneUri The Uri of the ringtone to be set.
   1978              */
   1979             public void setRingtoneURI(String ringtoneUri) {
   1980                 ProviderSettings.setRingtoneURI(mContentResolver, mProviderId, ringtoneUri);
   1981             }
   1982 
   1983             /**
   1984              * Get the Uri String of the current ringtone.
   1985              *
   1986              * @return The Uri String of the current ringtone.
   1987              */
   1988             public String getRingtoneURI() {
   1989                 return getString(SETTING_RINGTONE, SETTING_RINGTONE_DEFAULT);
   1990             }
   1991 
   1992             /**
   1993              * Set whether or not to show mobile indicator to friends.
   1994              *
   1995              * @param showMobile whether or not to show mobile indicator.
   1996              */
   1997             public void setShowMobileIndicator(boolean showMobile) {
   1998                 ProviderSettings.setShowMobileIndicator(mContentResolver, mProviderId, showMobile);
   1999             }
   2000 
   2001             /**
   2002              * Gets whether or not to show mobile indicator.
   2003              *
   2004              * @return Whether or not to show mobile indicator.
   2005              */
   2006             public boolean getShowMobileIndicator() {
   2007                 return getBoolean(SETTING_SHOW_MOBILE_INDICATOR,
   2008                         true /* by default show mobile indicator */);
   2009             }
   2010 
   2011             /**
   2012              * Set whether or not to show as away when device is idle.
   2013              *
   2014              * @param showAway whether or not to show as away when device is idle.
   2015              */
   2016             public void setShowAwayOnIdle(boolean showAway) {
   2017                 ProviderSettings.setShowAwayOnIdle(mContentResolver, mProviderId, showAway);
   2018             }
   2019 
   2020             /**
   2021              * Get whether or not to show as away when device is idle.
   2022              *
   2023              * @return Whether or not to show as away when device is idle.
   2024              */
   2025             public boolean getShowAwayOnIdle() {
   2026                 return getBoolean(SETTING_SHOW_AWAY_ON_IDLE,
   2027                         true /* by default show as away on idle*/);
   2028             }
   2029 
   2030             /**
   2031              * Set whether or not to upload heartbeat stat.
   2032              *
   2033              * @param uploadStat whether or not to upload heartbeat stat.
   2034              */
   2035             public void setUploadHeartbeatStat(boolean uploadStat) {
   2036                 ProviderSettings.setUploadHeartbeatStat(mContentResolver, mProviderId, uploadStat);
   2037             }
   2038 
   2039             /**
   2040              * Get whether or not to upload heartbeat stat.
   2041              *
   2042              * @return Whether or not to upload heartbeat stat.
   2043              */
   2044             public boolean getUploadHeartbeatStat() {
   2045                 return getBoolean(SETTING_UPLOAD_HEARTBEAT_STAT,
   2046                         false /* by default do not upload */);
   2047             }
   2048 
   2049             /**
   2050              * Set the last received heartbeat interval from the server.
   2051              *
   2052              * @param interval the last received heartbeat interval from the server.
   2053              */
   2054             public void setHeartbeatInterval(long interval) {
   2055                 ProviderSettings.setHeartbeatInterval(mContentResolver, mProviderId, interval);
   2056             }
   2057 
   2058             /**
   2059              * Get the last received heartbeat interval from the server.
   2060              *
   2061              * @return the last received heartbeat interval from the server.
   2062              */
   2063             public long getHeartbeatInterval() {
   2064                 return getLong(SETTING_HEARTBEAT_INTERVAL, 0L /* an invalid default interval */);
   2065             }
   2066 
   2067             /**
   2068              * Set the JID resource.
   2069              *
   2070              * @param jidResource the jid resource to be stored.
   2071              */
   2072             public void setJidResource(String jidResource) {
   2073                 ProviderSettings.setJidResource(mContentResolver, mProviderId, jidResource);
   2074             }
   2075             /**
   2076              * Get the JID resource used for the Google Talk connection
   2077              *
   2078              * @return the JID resource stored.
   2079              */
   2080             public String getJidResource() {
   2081                 return getString(SETTING_JID_RESOURCE, null);
   2082             }
   2083 
   2084             /**
   2085              * Convenience function for retrieving a single settings value
   2086              * as a boolean.
   2087              *
   2088              * @param name The name of the setting to retrieve.
   2089              * @param def Value to return if the setting is not defined.
   2090              * @return The setting's current value, or 'def' if it is not defined.
   2091              */
   2092             private boolean getBoolean(String name, boolean def) {
   2093                 ContentValues values = getValues(name);
   2094                 return values != null ? values.getAsBoolean(VALUE) : def;
   2095             }
   2096 
   2097             /**
   2098              * Convenience function for retrieving a single settings value
   2099              * as a String.
   2100              *
   2101              * @param name The name of the setting to retrieve.
   2102              * @param def The value to return if the setting is not defined.
   2103              * @return The setting's current value or 'def' if it is not defined.
   2104              */
   2105             private String getString(String name, String def) {
   2106                 ContentValues values = getValues(name);
   2107                 return values != null ? values.getAsString(VALUE) : def;
   2108             }
   2109 
   2110             /**
   2111              * Convenience function for retrieving a single settings value
   2112              * as an Integer.
   2113              *
   2114              * @param name The name of the setting to retrieve.
   2115              * @param def The value to return if the setting is not defined.
   2116              * @return The setting's current value or 'def' if it is not defined.
   2117              */
   2118             private int getInteger(String name, int def) {
   2119                 ContentValues values = getValues(name);
   2120                 return values != null ? values.getAsInteger(VALUE) : def;
   2121             }
   2122 
   2123             /**
   2124              * Convenience function for retrieving a single settings value
   2125              * as a Long.
   2126              *
   2127              * @param name The name of the setting to retrieve.
   2128              * @param def The value to return if the setting is not defined.
   2129              * @return The setting's current value or 'def' if it is not defined.
   2130              */
   2131             private long getLong(String name, long def) {
   2132                 ContentValues values = getValues(name);
   2133                 return values != null ? values.getAsLong(VALUE) : def;
   2134             }
   2135         }
   2136 
   2137     }
   2138 
   2139 
   2140     /**
   2141      * Columns for IM branding resource map cache table. This table caches the result of
   2142      * loading the branding resources to speed up IM landing page start.
   2143      */
   2144     public interface BrandingResourceMapCacheColumns {
   2145         /**
   2146          * The provider ID
   2147          * <P>Type: INTEGER</P>
   2148          */
   2149         String PROVIDER_ID = "provider_id";
   2150         /**
   2151          * The application resource ID
   2152          * <P>Type: INTEGER</P>
   2153          */
   2154         String APP_RES_ID = "app_res_id";
   2155         /**
   2156          * The plugin resource ID
   2157          * <P>Type: INTEGER</P>
   2158          */
   2159         String PLUGIN_RES_ID = "plugin_res_id";
   2160     }
   2161 
   2162     /**
   2163      * The table for caching the result of loading IM branding resources.
   2164      */
   2165     public static final class BrandingResourceMapCache
   2166         implements BaseColumns, BrandingResourceMapCacheColumns {
   2167         /**
   2168          * The content:// style URL for this table.
   2169          */
   2170         public static final Uri CONTENT_URI = Uri.parse("content://imps/brandingResMapCache");
   2171     }
   2172 
   2173 
   2174 
   2175     /**
   2176      * //TODO: move these to MCS specific provider.
   2177      * The following are MCS stuff, and should really live in a separate provider specific to
   2178      * MCS code.
   2179      */
   2180 
   2181     /**
   2182      * Columns from OutgoingRmq table
   2183      */
   2184     public interface OutgoingRmqColumns {
   2185         String RMQ_ID = "rmq_id";
   2186         String TIMESTAMP = "ts";
   2187         String DATA = "data";
   2188         String PROTOBUF_TAG = "type";
   2189     }
   2190 
   2191     /**
   2192      * //TODO: we should really move these to their own provider and database.
   2193      * The table for storing outgoing rmq packets.
   2194      */
   2195     public static final class OutgoingRmq implements BaseColumns, OutgoingRmqColumns {
   2196         private static String[] RMQ_ID_PROJECTION = new String[] {
   2197                 RMQ_ID,
   2198         };
   2199 
   2200         /**
   2201          * queryHighestRmqId
   2202          *
   2203          * @param resolver the content resolver
   2204          * @return the highest rmq id assigned to the rmq packet, or 0 if there are no rmq packets
   2205          *         in the OutgoingRmq table.
   2206          */
   2207         public static final long queryHighestRmqId(ContentResolver resolver) {
   2208             Cursor cursor = resolver.query(Imps.OutgoingRmq.CONTENT_URI_FOR_HIGHEST_RMQ_ID,
   2209                     RMQ_ID_PROJECTION,
   2210                     null, // selection
   2211                     null, // selection args
   2212                     null  // sort
   2213                     );
   2214 
   2215             long retVal = 0;
   2216             try {
   2217                 //if (DBG) log("initializeRmqid: cursor.count= " + cursor.count());
   2218 
   2219                 if (cursor.moveToFirst()) {
   2220                     retVal = cursor.getLong(cursor.getColumnIndexOrThrow(RMQ_ID));
   2221                 }
   2222             } finally {
   2223                 cursor.close();
   2224             }
   2225 
   2226             return retVal;
   2227         }
   2228 
   2229         /**
   2230          * The content:// style URL for this table.
   2231          */
   2232         public static final Uri CONTENT_URI = Uri.parse("content://imps/outgoingRmqMessages");
   2233 
   2234         /**
   2235          * The content:// style URL for the highest rmq id for the outgoing rmq messages
   2236          */
   2237         public static final Uri CONTENT_URI_FOR_HIGHEST_RMQ_ID =
   2238                 Uri.parse("content://imps/outgoingHighestRmqId");
   2239 
   2240         /**
   2241          * The default sort order for this table.
   2242          */
   2243         public static final String DEFAULT_SORT_ORDER = "rmq_id ASC";
   2244     }
   2245 
   2246     /**
   2247      * Columns for the LastRmqId table, which stores a single row for the last client rmq id
   2248      * sent to the server.
   2249      */
   2250     public interface LastRmqIdColumns {
   2251         String RMQ_ID = "rmq_id";
   2252     }
   2253 
   2254     /**
   2255      * //TODO: move these out into their own provider and database
   2256      * The table for storing the last client rmq id sent to the server.
   2257      */
   2258     public static final class LastRmqId implements BaseColumns, LastRmqIdColumns {
   2259         private static String[] PROJECTION = new String[] {
   2260                 RMQ_ID,
   2261         };
   2262 
   2263         /**
   2264          * queryLastRmqId
   2265          *
   2266          * queries the last rmq id saved in the LastRmqId table.
   2267          *
   2268          * @param resolver the content resolver.
   2269          * @return the last rmq id stored in the LastRmqId table, or 0 if not found.
   2270          */
   2271         public static final long queryLastRmqId(ContentResolver resolver) {
   2272             Cursor cursor = resolver.query(Imps.LastRmqId.CONTENT_URI,
   2273                     PROJECTION,
   2274                     null, // selection
   2275                     null, // selection args
   2276                     null  // sort
   2277                     );
   2278 
   2279             long retVal = 0;
   2280             try {
   2281                 if (cursor.moveToFirst()) {
   2282                     retVal = cursor.getLong(cursor.getColumnIndexOrThrow(RMQ_ID));
   2283                 }
   2284             } finally {
   2285                 cursor.close();
   2286             }
   2287 
   2288             return retVal;
   2289         }
   2290 
   2291         /**
   2292          * saveLastRmqId
   2293          *
   2294          * saves the rmqId to the lastRmqId table. This will override the existing row if any,
   2295          * as we only keep one row of data in this table.
   2296          *
   2297          * @param resolver the content resolver.
   2298          * @param rmqId the rmq id to be saved.
   2299          */
   2300         public static final void saveLastRmqId(ContentResolver resolver, long rmqId) {
   2301             ContentValues values = new ContentValues();
   2302 
   2303             // always replace the first row.
   2304             values.put(_ID, 1);
   2305             values.put(RMQ_ID, rmqId);
   2306             resolver.insert(CONTENT_URI, values);
   2307         }
   2308 
   2309         /**
   2310          * The content:// style URL for this table.
   2311          */
   2312         public static final Uri CONTENT_URI = Uri.parse("content://imps/lastRmqId");
   2313     }
   2314 
   2315     /**
   2316      * Columns for the s2dRmqIds table, which stores the server-to-device message
   2317      * persistent ids. These are used in the RMQ2 protocol, where in the login request, the
   2318      * client selective acks these s2d ids to the server.
   2319      */
   2320     public interface ServerToDeviceRmqIdsColumn {
   2321         String RMQ_ID = "rmq_id";
   2322     }
   2323 
   2324     public static final class ServerToDeviceRmqIds implements BaseColumns,
   2325             ServerToDeviceRmqIdsColumn {
   2326 
   2327         /**
   2328          * The content:// style URL for this table.
   2329          */
   2330         public static final Uri CONTENT_URI = Uri.parse("content://imps/s2dids");
   2331     }
   2332 
   2333 }
   2334