Imps.java revision c84f5b8faa3fac30fabe6b21ff30b7c98a36832e
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
17package com.android.im.provider;
18
19import android.content.ContentQueryMap;
20import android.content.ContentResolver;
21import android.content.ContentUris;
22import android.content.ContentValues;
23import android.database.Cursor;
24import android.net.Uri;
25import android.os.Handler;
26import android.provider.BaseColumns;
27
28import java.util.HashMap;
29
30/**
31 * The IM provider stores all information about roster contacts, chat messages, presence, etc.
32 *
33 * @hide
34 */
35public 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