1package com.android.bluetooth.tests;
2
3import java.io.FileInputStream;
4import java.io.FileNotFoundException;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.InputStream;
8import java.io.UnsupportedEncodingException;
9import java.text.SimpleDateFormat;
10import java.util.ArrayList;
11import java.util.Date;
12import java.util.LinkedHashMap;
13
14import android.annotation.TargetApi;
15import android.content.ContentResolver;
16import android.content.ContentValues;
17import android.content.Context;
18import android.database.Cursor;
19import android.net.Uri;
20import android.os.Bundle;
21import android.os.Debug;
22import android.os.ParcelFileDescriptor;
23import android.provider.BaseColumns;
24import android.provider.Telephony.Mms;
25import android.provider.Telephony.MmsSms;
26import android.provider.Telephony.Threads;
27import android.test.AndroidTestCase;
28import android.util.Log;
29
30import com.android.bluetooth.map.BluetoothMapMasInstance;
31import com.android.bluetooth.map.BluetoothMapAccountItem;
32import com.android.bluetooth.map.BluetoothMapAccountLoader;
33import com.android.bluetooth.map.BluetoothMapAppParams;
34import com.android.bluetooth.map.BluetoothMapContent;
35import com.android.bluetooth.map.BluetoothMapFolderElement;
36import com.android.bluetooth.map.BluetoothMapMessageListing;
37import com.android.bluetooth.map.BluetoothMapUtils;
38import com.android.bluetooth.map.BluetoothMapUtils.TYPE;
39import com.android.bluetooth.map.MapContact;
40import com.android.bluetooth.map.SmsMmsContacts;
41import com.android.bluetooth.mapapi.BluetoothMapContract;
42
43public class BluetoothMapContentTest extends AndroidTestCase {
44
45    private static final String TAG = "BluetoothMapContentTest";
46
47    private static final boolean D = true;
48
49    private Context mContext;
50    private ContentResolver mResolver;
51    private SmsMmsContacts mContacts = new SmsMmsContacts();
52
53    private BluetoothMapFolderElement mCurrentFolder;
54    private BluetoothMapAccountItem mAccount = null;
55
56    private static final int MAS_ID = 0;
57    private static final int REMOTE_FEATURE_MASK = 0x07FFFFFF;
58    private static final BluetoothMapMasInstance mMasInstance =
59            new MockMasInstance(MAS_ID, REMOTE_FEATURE_MASK);
60
61
62    private Uri mEmailUri = null;
63    private Uri mEmailMessagesUri = null;
64    private Uri mEmailFolderUri = null;
65    private Uri mEmailAccountUri = null;
66
67    static final String[] EMAIL_ACCOUNT_PROJECTION = new String[] {
68        BluetoothMapContract.MessageColumns.FOLDER_ID,
69        BluetoothMapContract.MessageColumns.ACCOUNT_ID,
70    };
71
72    private void printAccountInfo(Cursor c) {
73        if (D) Log.d(TAG, BluetoothMapContract.MessageColumns.ACCOUNT_ID + " : " +
74                c.getInt(c.getColumnIndex(BluetoothMapContract.MessageColumns.ACCOUNT_ID)) );
75    }
76
77    static final String[] BT_MESSAGE_ID_PROJECTION = new String[] {
78        BluetoothMapContract.MessageColumns._ID,
79        BluetoothMapContract.MessageColumns.DATE,
80    };
81
82    static final String[] BT_MESSAGE_PROJECTION = BluetoothMapContract.BT_MESSAGE_PROJECTION;
83
84    static final String[] BT_ACCOUNT_PROJECTION = BluetoothMapContract.BT_ACCOUNT_PROJECTION;
85
86    static final String[] BT_FOLDER_PROJECTION = BluetoothMapContract.BT_FOLDER_PROJECTION;
87
88    BluetoothMapAccountLoader loader;
89    LinkedHashMap<BluetoothMapAccountItem, ArrayList<BluetoothMapAccountItem>> mFullList;
90
91    public BluetoothMapContentTest() {
92        super();
93    }
94
95    private void initTestSetup(){
96        mContext = this.getContext();
97        mResolver = mContext.getContentResolver();
98
99        // find enabled account
100        loader    = new BluetoothMapAccountLoader(mContext);
101        mFullList = loader.parsePackages(false);
102        String accountId = getEnabledAccount();
103        Uri tmpEmailUri = Uri.parse("content://com.android.email.bluetoothprovider/");
104
105        mEmailUri = Uri.withAppendedPath(tmpEmailUri, accountId + "/");
106        mEmailMessagesUri = Uri.parse(mEmailUri + BluetoothMapContract.TABLE_MESSAGE);
107        mEmailFolderUri = Uri.parse(mEmailUri + BluetoothMapContract.TABLE_FOLDER);
108        mEmailAccountUri = Uri.parse(tmpEmailUri + BluetoothMapContract.TABLE_ACCOUNT);
109
110        buildFolderStructure();
111
112    }
113
114    public String getEnabledAccount(){
115        if(D)Log.d(TAG,"getEnabledAccountItems()\n");
116        String account = null;
117        for(BluetoothMapAccountItem app:mFullList.keySet()){
118            ArrayList<BluetoothMapAccountItem> accountList = mFullList.get(app);
119            for(BluetoothMapAccountItem acc: accountList){
120                mAccount = acc;
121                account = acc.getId();
122                break;
123            }
124        }
125        return account;
126    }
127
128    private void buildFolderStructure(){
129        mCurrentFolder = new BluetoothMapFolderElement("root", null); // This will be the root element
130        BluetoothMapFolderElement tmpFolder;
131        tmpFolder = mCurrentFolder.addFolder("telecom"); // root/telecom
132        tmpFolder = tmpFolder.addFolder("msg");          // root/telecom/msg
133        if(mEmailFolderUri != null) {
134            addEmailFolders(tmpFolder);
135        }
136    }
137
138    private void addEmailFolders(BluetoothMapFolderElement parentFolder) {
139        BluetoothMapFolderElement newFolder;
140        String where = BluetoothMapContract.FolderColumns.PARENT_FOLDER_ID +
141                        " = " + parentFolder.getFolderId();
142        Cursor c = mContext.getContentResolver().query(mEmailFolderUri,
143                        BluetoothMapContract.BT_FOLDER_PROJECTION, where, null, null);
144        if (c != null) {
145            c.moveToPosition(-1);
146            while (c.moveToNext()) {
147                String name = c.getString(c.getColumnIndex(BluetoothMapContract.FolderColumns.NAME));
148                long id = c.getLong(c.getColumnIndex(BluetoothMapContract.FolderColumns._ID));
149                newFolder = parentFolder.addEmailFolder(name, id);
150                addEmailFolders(newFolder); // Use recursion to add any sub folders
151            }
152            c.close();
153        } else {
154            if (D) Log.d(TAG, "addEmailFolders(): no elements found");
155        }
156    }
157
158    private BluetoothMapFolderElement getInbox() {
159        BluetoothMapFolderElement tmpFolderElement = null;
160
161        tmpFolderElement = mCurrentFolder.getSubFolder("telecom");
162        tmpFolderElement = tmpFolderElement.getSubFolder("msg");
163        tmpFolderElement = tmpFolderElement.getSubFolder("inbox");
164        return tmpFolderElement;
165    }
166
167    private BluetoothMapFolderElement getOutbox() {
168        BluetoothMapFolderElement tmpFolderElement = null;
169
170        tmpFolderElement = mCurrentFolder.getSubFolder("telecom");
171        tmpFolderElement = tmpFolderElement.getSubFolder("msg");
172        tmpFolderElement = tmpFolderElement.getSubFolder("outbox");
173        return tmpFolderElement;
174    }
175
176
177    private String getDateTimeString(long timestamp) {
178        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
179        Date date = new Date(timestamp);
180        return format.format(date); // Format to YYYYMMDDTHHMMSS local time
181    }
182
183    private void printCursor(Cursor c) {
184        StringBuilder sb = new StringBuilder();
185        sb.append("\nprintCursor:\n");
186        for(int i = 0; i < c.getColumnCount(); i++) {
187            if(c.getColumnName(i).equals(BluetoothMapContract.MessageColumns.DATE)){
188                sb.append("  ").append(c.getColumnName(i))
189                    .append(" : ").append(getDateTimeString(c.getLong(i))).append("\n");
190            } else {
191                sb.append("  ").append(c.getColumnName(i))
192                    .append(" : ").append(c.getString(i)).append("\n");
193            }
194        }
195        Log.d(TAG, sb.toString());
196    }
197
198    private void dumpMessageContent(Cursor c) {
199        long id = c.getLong(c.getColumnIndex(BluetoothMapContract.MessageColumns._ID));
200        Uri uri = Uri.parse(mEmailMessagesUri + "/" + id
201                + "/" + BluetoothMapContract.FILE_MSG_NO_ATTACHMENTS);
202        FileInputStream is = null;
203        ParcelFileDescriptor fd = null;
204        int count;
205        try {
206            fd = mResolver.openFileDescriptor(uri, "r");
207            is = new FileInputStream(fd.getFileDescriptor());
208            byte[] buffer = new byte[1024];
209
210            while((count = is.read(buffer)) != -1) {
211                Log.d(TAG, new String(buffer,0, count));
212            }
213
214
215        } catch (FileNotFoundException e) {
216            Log.w(TAG, e);
217        } catch (IOException e) {
218            Log.w(TAG, e);
219        }
220        finally {
221            try {
222               if(is != null)
223                    is.close();
224            } catch (IOException e) {}
225               try {
226                if(fd != null)
227                    fd.close();
228            } catch (IOException e) {}
229        }
230    }
231
232    /**
233     * Create a new message in the database outbox, based on the content of c.
234     * @param c
235     */
236    private void writeMessageContent(Cursor c) {
237        long id = c.getLong(c.getColumnIndex(BluetoothMapContract.MessageColumns._ID));
238        Uri uri = Uri.parse(mEmailMessagesUri + "/" + id + "/"
239                + BluetoothMapContract.FILE_MSG_NO_ATTACHMENTS);
240        FileInputStream is = null;
241        ParcelFileDescriptor fd = null;
242        FileOutputStream os = null;
243        ParcelFileDescriptor fdOut = null;
244
245        ContentValues newMessage = new ContentValues();
246        BluetoothMapFolderElement outFolder = getOutbox();
247        newMessage.put(BluetoothMapContract.MessageColumns.FOLDER_ID, outFolder.getFolderId());
248        // Now insert the empty message into outbox (Maybe it should be draft first, and then a move?)
249        // TODO: Examine if we need to set some additional flags, e.g. visable?
250        Uri uriOut = mResolver.insert(mEmailMessagesUri, newMessage);
251        int count;
252        try {
253            fd = mResolver.openFileDescriptor(uri, "r");
254            is = new FileInputStream(fd.getFileDescriptor());
255            fdOut = mResolver.openFileDescriptor(uri, "w");
256            os = new FileOutputStream(fdOut.getFileDescriptor());
257            byte[] buffer = new byte[1024];
258
259            while((count = is.read(buffer)) != -1) {
260                Log.d(TAG, new String(buffer,0, count));
261                os.write(buffer, 0, count);
262            }
263        } catch (FileNotFoundException e) {
264            Log.w(TAG, e);
265        } catch (IOException e) {
266            Log.w(TAG, e);
267        }
268        finally {
269            try {
270               if(is != null)
271                    is.close();
272            } catch (IOException e) {}
273               try {
274                if(fd != null)
275                    fd.close();
276            } catch (IOException e) {}
277               try {
278                   if(os != null)
279                        os.close();
280                } catch (IOException e) {}
281                   try {
282                    if(fdOut != null)
283                        fdOut.close();
284                } catch (IOException e) {}
285        }
286    }
287
288    private void writeMessage(Cursor c) {
289        Log.d(TAG, "c.getCount() = " + c.getCount());
290            c.moveToPosition(-1);
291        if (c.moveToNext()) {
292            writeMessageContent(c);
293        }
294        c.close();
295    }
296
297
298    private void dumpCursor(Cursor c) {
299        Log.d(TAG, "c.getCount() = " + c.getCount());
300        c.moveToPosition(-1);
301        while (c.moveToNext()) {
302            printCursor(c);
303        }
304        c.close();
305    }
306
307    private void callBluetoothProvider() {
308        Log.d(TAG, "**** Test call into email provider ****");
309        int accountId = 0;
310        int mailboxId = 0;
311
312        Log.d(TAG, "contentUri = " + mEmailMessagesUri);
313
314        Cursor c = mResolver.query(mEmailMessagesUri, EMAIL_ACCOUNT_PROJECTION,
315                null, null, "_id DESC");
316        if (c != null) {
317            Log.d(TAG, "c.getCount() = " + c.getCount());
318            c.moveToPosition(-1);
319            while (c.moveToNext()) {
320                printAccountInfo(c);
321                mailboxId = c.getInt(c.getColumnIndex(
322                                BluetoothMapContract.MessageColumns.FOLDER_ID));
323                accountId = c.getInt(c.getColumnIndex(
324                                BluetoothMapContract.MessageColumns.ACCOUNT_ID));
325            }
326           c.close();
327        } else {
328            Log.d(TAG, "query failed");
329        }
330
331        final Bundle extras = new Bundle(2);
332        /* TODO: find mailbox from DB */
333        extras.putLong(BluetoothMapContract.EXTRA_UPDATE_FOLDER_ID, mailboxId);
334        extras.putLong(BluetoothMapContract.EXTRA_UPDATE_ACCOUNT_ID, accountId);
335        Bundle myBundle = mResolver.call(mEmailUri, BluetoothMapContract.METHOD_UPDATE_FOLDER,
336                                            null, extras);
337    }
338
339
340    public void testMsgListing() {
341        initTestSetup();
342        BluetoothMapContent mBtMapContent = new BluetoothMapContent(mContext, mAccount,
343                mMasInstance);
344        BluetoothMapAppParams appParams = new BluetoothMapAppParams();
345        Log.d(TAG, "**** testMsgListing **** ");
346        BluetoothMapFolderElement fe = getInbox();
347
348        if (fe != null) {
349            if (D) Log.d(TAG, "folder name=" + fe.getName());
350
351            appParams.setFilterMessageType(0x0B);
352            appParams.setMaxListCount(1024);
353            appParams.setStartOffset(0);
354
355            BluetoothMapMessageListing msgListing = mBtMapContent.msgListing(fe, appParams);
356            int listCount = msgListing.getCount();
357            int msgListingSize = mBtMapContent.msgListingSize(fe, appParams);
358
359            if (listCount == msgListingSize) {
360                Log.d(TAG, "testMsgListing - " + listCount );
361            }
362            else {
363                Log.d(TAG, "testMsgListing - None");
364            }
365        }
366        else {
367            Log.d(TAG, "testMsgListing - failed ");
368        }
369
370    }
371
372    public void testMsgListingUnread() {
373        initTestSetup();
374        BluetoothMapContent mBtMapContent = new BluetoothMapContent(mContext, mAccount,
375                mMasInstance);
376        BluetoothMapAppParams appParams = new BluetoothMapAppParams();
377        Log.d(TAG, "**** testMsgListingUnread **** ");
378        BluetoothMapFolderElement fe = getInbox();
379
380        if (fe != null) {
381
382            appParams.setFilterReadStatus(0x01);
383            appParams.setFilterMessageType(0x0B);
384            appParams.setMaxListCount(1024);
385            appParams.setStartOffset(0);
386
387            BluetoothMapMessageListing msgListing = mBtMapContent.msgListing(fe, appParams);
388
389            int listCount = msgListing.getCount();
390            if (msgListing.getCount() > 0) {
391                Log.d(TAG, "testMsgListingUnread - " + listCount );
392            }
393            else {
394                Log.d(TAG, "testMsgListingUnread - None");
395            }
396        }
397        else {
398            Log.d(TAG, "testMsgListingUnread - getInbox failed ");
399        }
400    }
401
402    public void testMsgListingWithOriginator() {
403        initTestSetup();
404        BluetoothMapContent mBtMapContent = new BluetoothMapContent(mContext, mAccount,
405                mMasInstance);
406        BluetoothMapAppParams appParams = new BluetoothMapAppParams();
407        Log.d(TAG, "**** testMsgListingUnread **** ");
408        BluetoothMapFolderElement fe = getInbox();
409
410        if (fe != null) {
411
412            appParams.setFilterOriginator("*scsc.*");
413            appParams.setFilterMessageType(0x0B);
414            appParams.setMaxListCount(1024);
415            appParams.setStartOffset(0);
416
417            BluetoothMapMessageListing msgListing = mBtMapContent.msgListing(fe, appParams);
418
419            int listCount = msgListing.getCount();
420            if (msgListing.getCount() > 0) {
421                Log.d(TAG, "testMsgListingWithOriginator - " + listCount );
422            }
423            else {
424                Log.d(TAG, "testMsgListingWithOriginator - None");
425            }
426        } else {
427            Log.d(TAG, "testMsgListingWithOriginator - getInbox failed ");
428        }
429    }
430
431    public void testGetMessages() {
432        initTestSetup();
433        BluetoothMapContent mBtMapContent = new BluetoothMapContent(mContext, mAccount,
434                mMasInstance);
435        BluetoothMapAppParams appParams = new BluetoothMapAppParams();
436        Log.d(TAG, "**** testGetMessages **** ");
437        BluetoothMapFolderElement fe = getInbox();
438
439        if (fe != null) {
440            appParams.setAttachment(0);
441            appParams.setCharset(BluetoothMapContent.MAP_MESSAGE_CHARSET_UTF8);
442
443            //get message handles
444            Cursor c = mResolver.query(mEmailMessagesUri, BT_MESSAGE_ID_PROJECTION,
445                    null, null, "_id DESC");
446            if (c != null) {
447                c.moveToPosition(-1);
448                while (c.moveToNext()) {
449                    Long id = c.getLong(c.getColumnIndex(BluetoothMapContract.MessageColumns._ID));
450                    String handle = BluetoothMapUtils.getMapHandle(id, TYPE.EMAIL);
451                    try {
452                        // getMessage
453                        byte[] bytes = mBtMapContent.getMessage(handle, appParams, fe, "1.1");
454                        Log.d(TAG, "testGetMessages id=" + id + ", handle=" + handle +
455                                ", length=" + bytes.length );
456                        String testPrint = new String(bytes);
457                        Log.d(TAG, "testGetMessage (only dump first part):\n" + testPrint );
458                    } catch (UnsupportedEncodingException e) {
459                        Log.w(TAG, e);
460                    } finally {
461
462                    }
463                }
464            } else {
465                Log.d(TAG, "testGetMessages - no cursor ");
466            }
467        } else {
468            Log.d(TAG, "testGetMessages - getInbox failed ");
469        }
470
471    }
472
473    public void testDumpAccounts() {
474        initTestSetup();
475        Log.d(TAG, "**** testDumpAccounts **** \n from: " + mEmailAccountUri.toString());
476        Cursor c = mResolver.query(mEmailAccountUri, BT_ACCOUNT_PROJECTION, null, null, "_id DESC");
477        if (c != null) {
478            dumpCursor(c);
479        } else {
480            Log.d(TAG, "query failed");
481        }
482        Log.w(TAG, "testDumpAccounts(): ThreadId: " + Thread.currentThread().getId());
483
484    }
485
486    public void testAccountUpdate() {
487        initTestSetup();
488        Log.d(TAG, "**** testAccountUpdate **** \n of: " + mEmailAccountUri.toString());
489        Cursor c = mResolver.query(mEmailAccountUri, BT_ACCOUNT_PROJECTION, null, null, "_id DESC");
490
491        if (c != null) {
492            c.moveToPosition(-1);
493            while (c.moveToNext()) {
494                printCursor(c);
495                Long id = c.getLong(c.getColumnIndex(BluetoothMapContract.AccountColumns._ID));
496                int exposeFlag = c.getInt(
497                        c.getColumnIndex(BluetoothMapContract.AccountColumns.FLAG_EXPOSE));
498                String where = BluetoothMapContract.AccountColumns._ID + " = " + id;
499                ContentValues values = new ContentValues();
500                if(exposeFlag == 1) {
501                    values.put(BluetoothMapContract.AccountColumns.FLAG_EXPOSE, (int) 0);
502                } else {
503                    values.put(BluetoothMapContract.AccountColumns.FLAG_EXPOSE, (int) 1);
504                }
505                Log.i(TAG, "Calling update() with selection: " + where +
506                           "values(exposeFlag): " +
507                            values.getAsInteger(BluetoothMapContract.AccountColumns.FLAG_EXPOSE));
508                mResolver.update(mEmailAccountUri, values, where, null);
509            }
510            c.close();
511        }
512
513    }
514
515    public void testDumpMessages() {
516        initTestSetup();
517
518        if (D) Log.d(TAG, "**** testDumpMessages **** \n uri=" + mEmailMessagesUri.toString());
519        BluetoothMapFolderElement fe = getInbox();
520        if (fe != null)
521        {
522            String where ="";
523            //where = BluetoothMapContract.MessageColumns.FOLDER_ID + " = " + fe.getEmailFolderId();
524            Cursor c = mResolver.query(mEmailMessagesUri, BT_MESSAGE_PROJECTION,
525                    where, null, "_id DESC");
526            if (c != null) {
527                dumpCursor(c);
528            } else {
529                if (D) Log.d(TAG, "query failed");
530            }
531            if (D) Log.w(TAG, "dumpMessage(): ThreadId: " + Thread.currentThread().getId());
532        } else {
533            if (D) Log.w(TAG, "dumpMessage(): ThreadId: " + Thread.currentThread().getId());
534        }
535    }
536
537    public void testDumpMessageContent() {
538        initTestSetup();
539
540        Log.d(TAG, "**** testDumpMessageContent **** from: " + mEmailMessagesUri.toString());
541//        BluetoothMapFolderElement fe = getInbox();
542//        String where = BluetoothMapContract.MessageColumns.FOLDER_ID + " = " + fe.getEmailFolderId();
543//        where += " AND " + BluetoothMapContract.MessageColumns.FLAG_HIGH_PRIORITY + " = 0";
544
545        Cursor c = mResolver.query(mEmailMessagesUri, BT_MESSAGE_PROJECTION, null, null, "_id DESC");
546        if (c != null && c.moveToNext()) {
547            dumpMessageContent(c);
548        } else {
549            Log.d(TAG, "query failed");
550        }
551        Log.w(TAG, "dumpMessage(): ThreadId: " + Thread.currentThread().getId());
552    }
553
554    public void testWriteMessageContent() {
555        initTestSetup();
556        Log.d(TAG, "**** testWriteMessageContent **** from: " + mEmailMessagesUri.toString());
557        BluetoothMapFolderElement fe = getInbox();
558        String where = BluetoothMapContract.MessageColumns.FOLDER_ID + " = " + fe.getFolderId();
559//        where += " AND " + BluetoothMapContract.MessageColumns.HIGH_PRIORITY + " = 0";
560        Cursor c = mResolver.query(mEmailMessagesUri, BT_MESSAGE_PROJECTION, where, null, "_id DESC");
561        if (c != null) {
562            writeMessage(c);
563        } else {
564            Log.d(TAG, "query failed");
565        }
566        Log.w(TAG, "writeMessage(): ThreadId: " + Thread.currentThread().getId());
567    }
568
569    /*
570     * Handle test cases
571     */
572    private static final long HANDLE_TYPE_SMS_CDMA_MASK            = (((long)0x1)<<60);
573
574    public void testHandle() {
575        String handleStr = null;
576        Debug.startMethodTracing("str_format");
577        for(long i = 0; i < 10000; i++) {
578            handleStr = String.format("%016X",(i | HANDLE_TYPE_SMS_CDMA_MASK));
579        }
580        Debug.stopMethodTracing();
581        Debug.startMethodTracing("getHandleString");
582        for(long i = 0; i < 10000; i++) {
583            handleStr = BluetoothMapUtils.getLongAsString(i | HANDLE_TYPE_SMS_CDMA_MASK);
584        }
585        Debug.stopMethodTracing();
586    }
587
588    /*
589     * Folder test cases
590     */
591
592    public void testDumpEmailFolders() {
593        initTestSetup();
594        Debug.startMethodTracing();
595        String where = null;
596        Cursor c = mResolver.query(mEmailFolderUri, BT_FOLDER_PROJECTION, where, null, "_id DESC");
597        if (c != null) {
598            dumpCursor(c);
599            c.close();
600        } else {
601            Log.d(TAG, "query failed");
602        }
603        Debug.stopMethodTracing();
604    }
605
606    public void testFolderPath() {
607        initTestSetup();
608        Log.d(TAG, "**** testFolderPath **** ");
609        BluetoothMapFolderElement fe = getInbox();
610        BluetoothMapFolderElement folder = fe.getFolderById(fe.getFolderId());
611        if(folder == null) {
612            Log.d(TAG, "**** testFolderPath unable to find the folder with id: " +
613                    fe.getFolderId());
614        }
615        else {
616            Log.d(TAG, "**** testFolderPath found the folder with id: " +
617                    fe.getFolderId() + "\nFull path: " +
618                    folder.getFullPath());
619        }
620    }
621
622    public void testFolderElement() {
623        Log.d(TAG, "**** testFolderElement **** ");
624        BluetoothMapFolderElement fe = new BluetoothMapFolderElement("root", null);
625        fe = fe.addEmailFolder("MsG", 1);
626        fe.addEmailFolder("Outbox", 100);
627        fe.addEmailFolder("Sent", 200);
628        BluetoothMapFolderElement inbox = fe.addEmailFolder("Inbox", 300);
629        fe.addEmailFolder("Draft", 400);
630        fe.addEmailFolder("Deleted", 500);
631        inbox.addEmailFolder("keep", 301);
632        inbox.addEmailFolder("private", 302);
633        inbox.addEmailFolder("junk", 303);
634
635        BluetoothMapFolderElement folder = fe.getFolderById(400);
636        assertEquals("draft", folder.getName());
637        assertEquals("private", fe.getFolderById(302).getName());
638        assertEquals("junk", fe.getRoot().getFolderById(303).getName());
639        assertEquals("msg/inbox/keep", fe.getFolderById(301).getFullPath());
640    }
641
642    /*
643     * SMS test cases
644     */
645    public void testAddSmsEntries() {
646        int count = 1000;
647        mContext = this.getContext();
648        mResolver = mContext.getContentResolver();
649        ContentValues values[] = new ContentValues[count];
650        long date = System.currentTimeMillis();
651        Log.i(TAG, "Preparing messages...");
652        for (int x=0;x<count;x++){
653            //if (D) Log.d(TAG, "*** Adding dummy sms #"+x);
654
655            ContentValues item = new ContentValues(4);
656            item.put("address", "1234");
657            item.put("body", "test message "+x);
658            item.put("date", date);
659            item.put("read", "0");
660
661            values[x] = item;
662            // Uri mUri = mResolver.insert(Uri.parse("content://sms"), item);
663        }
664        Log.i(TAG, "Starting bulk insert...");
665        mResolver.bulkInsert(Uri.parse("content://sms"), values);
666        Log.i(TAG, "Bulk insert done.");
667    }
668
669    public void testAddSms() {
670        mContext = this.getContext();
671        mResolver = mContext.getContentResolver();
672        if (D) Log.d(TAG, "*** Adding dummy sms #");
673
674        ContentValues item = new ContentValues();
675        item.put("address", "1234");
676        item.put("body", "test message");
677        item.put("date", System.currentTimeMillis());
678        item.put("read", "0");
679
680        Uri mUri = mResolver.insert(Uri.parse("content://sms"), item);
681    }
682
683    public void testServiceSms() {
684        mContext = this.getContext();
685        mResolver = mContext.getContentResolver();
686        if (D) Log.d(TAG, "*** Adding dummy sms #");
687
688        ContentValues item = new ContentValues();
689        item.put("address", "C-Bonde");
690        item.put("body", "test message");
691        item.put("date", System.currentTimeMillis());
692        item.put("read", "0");
693
694        Uri mUri = mResolver.insert(Uri.parse("content://sms"), item);
695    }
696
697    /*
698     * MMS content test cases
699     */
700    public static final int MMS_FROM = 0x89;
701    public static final int MMS_TO = 0x97;
702    public static final int MMS_BCC = 0x81;
703    public static final int MMS_CC = 0x82;
704
705    private void printMmsAddr(long id) {
706        final String[] projection = null;
707        String selection = new String("msg_id=" + id);
708        String uriStr = String.format("content://mms/%d/addr", id);
709        Uri uriAddress = Uri.parse(uriStr);
710        Cursor c = mResolver.query(uriAddress, projection, selection, null, null);
711
712        if (c.moveToFirst()) {
713            do {
714                String add = c.getString(c.getColumnIndex("address"));
715                Integer type = c.getInt(c.getColumnIndex("type"));
716                if (type == MMS_TO) {
717                    if (D) Log.d(TAG, "   recipient: " + add + " (type: " + type + ")");
718                } else if (type == MMS_FROM) {
719                    if (D) Log.d(TAG, "   originator: " + add + " (type: " + type + ")");
720                } else {
721                    if (D) Log.d(TAG, "   address other: " + add + " (type: " + type + ")");
722                }
723                printCursor(c);
724
725            } while(c.moveToNext());
726        }
727    }
728
729    private void printMmsPartImage(long partid) {
730        String uriStr = String.format("content://mms/part/%d", partid);
731        Uri uriAddress = Uri.parse(uriStr);
732        int ch;
733        StringBuffer sb = new StringBuffer("");
734        InputStream is = null;
735
736        try {
737            is = mResolver.openInputStream(uriAddress);
738
739            while ((ch = is.read()) != -1) {
740                sb.append((char)ch);
741            }
742            if (D) Log.d(TAG, sb.toString());
743
744        } catch (IOException e) {
745            // do nothing for now
746            e.printStackTrace();
747        }
748    }
749
750    private void printMmsParts(long id) {
751        final String[] projection = null;
752        String selection = new String("mid=" + id);
753        String uriStr = String.format("content://mms/%d/part", id);
754        Uri uriAddress = Uri.parse(uriStr);
755        Cursor c = mResolver.query(uriAddress, projection, selection, null, null);
756
757        if (c.moveToFirst()) {
758            int i = 0;
759            do {
760                if (D) Log.d(TAG, "   part " + i++);
761                printCursor(c);
762
763                /* if (ct.equals("image/jpeg")) { */
764                /*     printMmsPartImage(partid); */
765                /* } */
766            } while(c.moveToNext());
767        }
768    }
769
770    public void dumpMmsTable() {
771        mContext = this.getContext();
772        mResolver = mContext.getContentResolver();
773
774        if (D) Log.d(TAG, "**** Dump of mms table ****");
775        Cursor c = mResolver.query(Mms.CONTENT_URI,
776                null, null, null, "_id DESC");
777        if (c != null) {
778            if (D) Log.d(TAG, "c.getCount() = " + c.getCount());
779            c.moveToPosition(-1);
780            while (c.moveToNext()) {
781                Log.d(TAG,"Message:");
782                printCursor(c);
783                long id = c.getLong(c.getColumnIndex(BaseColumns._ID));
784                Log.d(TAG,"Address:");
785                printMmsAddr(id);
786                Log.d(TAG,"Parts:");
787                printMmsParts(id);
788            }
789            c.close();
790        } else {
791            Log.d(TAG, "query failed");
792        }
793    }
794
795    /**
796     * This dumps the thread database.
797     * Interesting how useful this is.
798     *  - DATE is described to be the creation date of the thread. But it actually
799     *    contains the time-date of the last activity of the thread.
800     *  - RECIPIENTS is a list of the contacts related to the thread. The number can
801     *    be found for both MMS and SMS in the "canonical-addresses" table.
802     *  - The READ column tells if the thread have been read. (read = 1: no unread messages)
803     *  - The snippet is a small piece of text from the last message, and could be used as thread
804     *    name. Please however note that if we do this, the version-counter should change each
805     *    time a message is added to the thread. But since it changes the read attribute and
806     *    last activity, it changes anyway.
807     *  -
808     */
809
810
811    public void dumpThreadsTable() {
812        mContext = this.getContext();
813        mResolver = mContext.getContentResolver();
814        mContacts.clearCache();
815        Uri uri = Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build();
816
817        if (D) Log.d(TAG, "**** Dump of Threads table ****\nUri: " + uri);
818        Cursor c = mResolver.query(uri,
819                null, null, null, "_id DESC");
820        if (c != null) {
821            if (D) Log.d(TAG, "c.getCount() = " + c.getCount());
822            c.moveToPosition(-1);
823            while (c.moveToNext()) {
824                Log.d(TAG,"Threads:");
825                printCursor(c);
826                String ids = c.getString(c.getColumnIndex(Threads.RECIPIENT_IDS));
827                Log.d(TAG,"Address:");
828                printAddresses(ids);
829/*                Log.d(TAG,"Parts:");
830                printMmsParts(id);*/
831            }
832            c.close();
833        } else {
834            Log.d(TAG, "query failed");
835        }
836    }
837
838    /**
839     * This test shows the content of the canonicalAddresses table.
840     * Conclusion:
841     * The _id column matches the id's from the RECIPIENT_IDS column
842     * in the Threads table, hence are to be used to map from an id to
843     * a phone number, which then can be matched to a contact.
844     */
845    public void dumpCanAddrTable() {
846        mContext = this.getContext();
847        mResolver = mContext.getContentResolver();
848        Uri uri = Uri.parse("content://mms-sms/canonical-addresses");
849        uri = MmsSms.CONTENT_URI.buildUpon().appendPath("canonical-addresses").build();
850        dumpUri(uri);
851    }
852
853    public void dumpUri(Uri uri) {
854        if (D) Log.d(TAG, "**** Dump of table ****\nUri: " + uri);
855        Cursor c = mResolver.query(uri, null, null, null, null);
856        if (c != null) {
857            if (D) Log.d(TAG, "c.getCount() = " + c.getCount());
858            c.moveToPosition(-1);
859            while (c.moveToNext()) {
860                Log.d(TAG,"Entry: " + c.getPosition());
861                printCursor(c);
862            }
863            c.close();
864        } else {
865            Log.d(TAG, "query failed");
866        }
867    }
868
869    private void printAddresses(String idsStr) {
870        String[] ids = idsStr.split(" ");
871        for (String id : ids) {
872            long longId;
873            try {
874                longId = Long.parseLong(id);
875                String addr = mContacts.getPhoneNumber(mResolver, longId);
876                MapContact contact = mContacts.getContactNameFromPhone(addr, mResolver);
877                Log.d(TAG, "  id " + id + ": " + addr + " - " + contact.getName()
878                        + "  X-BT-UID: " + contact.getXBtUidString());
879            } catch (NumberFormatException ex) {
880                // skip this id
881                continue;
882            }
883        }
884    }
885
886}
887