Merge change 9294

* changes:
  Massive reworking of EAS serialization; much smaller and faster now
This commit is contained in:
Android (Google) Code Review 2009-08-01 18:03:58 -07:00
commit 5b571cf6ba
25 changed files with 1036 additions and 963 deletions

View File

@ -463,4 +463,8 @@
these mail accounts.</string>
<!-- Message that appears when adding a T-Online account -->
<string name="provider_note_t_online">Before setting up this email account, please visit the T-Online Web site and create a password for POP3 email access.</string>
<!-- Name of Microsoft Exchange account type; used by AccountManager -->
<string name="exchange_name">Exchange</string>
</resources>

View File

@ -23,5 +23,5 @@
<account-authenticator xmlns:android="http://schemas.android.com/apk/res/android"
android:accountType="com.android.exchange"
android:icon="@drawable/icon"
android:label="@string/app_name"
android:label="@string/exchange_name"
/>

View File

@ -121,7 +121,7 @@ public class Controller {
/**
* Enable/disable logging for external sync services
*
*
* Generally this should be called by anybody who changes Email.DEBUG
*/
public void serviceLogging(boolean debugEnabled) {
@ -275,7 +275,7 @@ public class Controller {
if (accountId < 0 || mailboxType < 0) {
String mes = "Invalid arguments " + accountId + ' ' + mailboxType;
Log.e(Email.LOG_TAG, mes);
throw new RuntimeException(mes);
throw new RuntimeException(mes);
}
Mailbox box = new Mailbox();
box.mAccountKey = accountId;
@ -339,13 +339,13 @@ public class Controller {
/**
* Delete a single message by moving it to the trash.
*
*
* This function has no callback, no result reporting, because the desired outcome
* is reflected entirely by changes to one or more cursors.
*
*
* @param messageId The id of the message to "delete".
* @param accountId The id of the message's account, or -1 if not known by caller
*
*
* TODO: Move out of UI thread
* TODO: "get account a for message m" should be a utility
* TODO: "get mailbox of type n for account a" should be a utility
@ -699,6 +699,8 @@ public class Controller {
// TODO should pass this back instead of looking it up here
// TODO smaller projection
Mailbox mbx = Mailbox.restoreMailboxWithId(mContext, mailboxId);
// The mailbox could have disappeared if the server commanded it
if (mbx == null) return;
long accountId = mbx.mAccountKey;
synchronized(mListeners) {
for (Result listener : mListeners) {

View File

@ -1756,6 +1756,7 @@ public abstract class EmailContent {
public static final int TYPE_CALENDAR = 0x41;
public static final int TYPE_CONTACTS = 0x42;
public static final int TYPE_TASKS = 0x43;
public static final int TYPE_EAS_ACCOUNT_MAILBOX = 0x44;
// Bit field flags
public static final int FLAG_HAS_CHILDREN = 1<<0;

View File

@ -62,8 +62,10 @@ public class EmailProvider extends ContentProvider {
// version 17: prevent duplication of mailboxes with the same serverId
// version 18: renamed syncFrequency to syncInterval for Account and Mailbox
// version 19: added triggers to keep track of unreadCount by Mailbox
// version 20: changed type of EAS account mailbox, making old databases invalid for EAS
// version 21: fixed broken trigger linking account deletion to the deletion of its HostAuth's
public static final int DATABASE_VERSION = 19;
public static final int DATABASE_VERSION = 21;
public static final int BODY_DATABASE_VERSION = 1;
public static final String EMAIL_AUTHORITY = "com.android.email.provider";
@ -376,7 +378,9 @@ public class EmailProvider extends ContentProvider {
" begin delete from " + Mailbox.TABLE_NAME +
" where " + MailboxColumns.ACCOUNT_KEY + "=old." + EmailContent.RECORD_ID +
"; delete from " + HostAuth.TABLE_NAME +
" where " + HostAuthColumns.ACCOUNT_KEY + "=old." + EmailContent.RECORD_ID +
" where " + EmailContent.RECORD_ID + "=old." + AccountColumns.HOST_AUTH_KEY_RECV +
"; delete from " + HostAuth.TABLE_NAME +
" where " + EmailContent.RECORD_ID + "=old." + AccountColumns.HOST_AUTH_KEY_SEND +
"; end");
}

View File

@ -17,7 +17,6 @@
package com.android.exchange;
import com.android.email.Email;
import com.android.email.mail.MessagingException;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Mailbox;
@ -90,7 +89,7 @@ public abstract class AbstractSyncService implements Runnable {
* is necessary. For consistency with the Email app's original
* functionality, success is indicated by a failure to throw an Exception
* (ugh). Parameters are self-explanatory
*
*
* @param host
* @param userName
* @param password
@ -105,7 +104,7 @@ public abstract class AbstractSyncService implements Runnable {
/**
* Sent by SyncManager to determine the state of a running sync This is
* currently unused
*
*
* @return status code
*/
public int getSyncStatus() {
@ -127,7 +126,7 @@ public abstract class AbstractSyncService implements Runnable {
/**
* The UI can call this static method to perform account validation. This method wraps each
* protocol's validateAccount method. Arguments are self-explanatory, except where noted.
*
*
* @param klass the protocol class (EasSyncService.class for example)
* @param host
* @param userName
@ -212,30 +211,17 @@ public abstract class AbstractSyncService implements Runnable {
* @param str the String to log
*/
public void userLog(String str) {
if (Eas.USER_DEBUG) {
if (Eas.USER_LOG) {
Log.i(TAG, str);
}
}
public void errorLog(String str) {
if (Eas.USER_DEBUG) {
if (Eas.USER_LOG) {
Log.e(TAG, str);
}
}
/**
* Convenience method to do test logging. Saves a bunch of repetitive code.
* Unlike user logging, TEST_DEBUG is declared final, so that testLog calls should get
* "compiled out" for non-debug builds.
*
* @param str the String to log
*/
protected void testLog(String str) {
if (Eas.TEST_DEBUG) {
Log.v(Email.LOG_TAG, str);
}
}
/**
* Implements a delay until there is some kind of network connectivity available. This method
* may be supplanted by functionality in SyncManager.
@ -277,11 +263,11 @@ public abstract class AbstractSyncService implements Runnable {
// What's below here is temporary
/**
/**
* PartRequest handling (common functionality)
* Can be overridden if desired, but IMAP/EAS both use the next three methods as-is
*/
public void addPartRequest(PartRequest req) {
synchronized (mPartRequests) {
mPartRequests.add(req);

View File

@ -22,15 +22,16 @@ package com.android.exchange;
*
*/
public class Eas {
// For use in collecting user logs
public static boolean USER_DEBUG = false; // DO NOT CHECK IN WITH THIS SET TO TRUE
// For temporary use while debugging
public static boolean TEST_DEBUG = false; // DO NOT CHECK IN WITH THIS SET TO TRUE
// For debugging
public static boolean WAIT_DEBUG = false; // DO NOT CHECK IN WITH THIS SET TO TRUE
public static boolean DEBUG = true; // DO NOT CHECK IN WITH THIS SET TO TRUE
public static final String VERSION = "0.1";
// The following two are for user logging (the second providing more detail)
public static boolean USER_LOG = false; // DO NOT CHECK IN WITH THIS SET TO TRUE
public static boolean PARSER_LOG = false; // DO NOT CHECK IN WITH THIS SET TO TRUE
public static final String VERSION = "0.2";
public static final String ACCOUNT_MANAGER_TYPE = "com.android.exchange";
public static final String ACCOUNT_MAILBOX = "__eas";
// From EAS spec
@ -60,7 +61,10 @@ public class Eas {
public static final int FOLDER_STATUS_OK = 1;
public static final int FOLDER_STATUS_INVALID_KEY = 9;
public void setUserDebug(boolean state) {
USER_DEBUG = state;
public static void setUserDebug(boolean state) {
// DEBUG takes precedence and is never true in a user build
if (!DEBUG) {
USER_LOG = state;
}
}
}

View File

@ -15,14 +15,12 @@
* limitations under the License.
*/
package com.android.exchange.adapter;
package com.android.exchange;
import com.android.email.provider.EmailContent.HostAuth;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns;
import com.android.exchange.EasSyncService;
import com.android.exchange.SyncManager;
import com.android.exchange.utility.Rfc822Formatter;
import android.content.ContentUris;

View File

@ -27,13 +27,14 @@ import com.android.email.provider.EmailContent.HostAuth;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message;
import com.android.exchange.adapter.EasContactsSyncAdapter;
import com.android.exchange.adapter.EasEmailSyncAdapter;
import com.android.exchange.adapter.EasFolderSyncParser;
import com.android.exchange.adapter.EasPingParser;
import com.android.exchange.adapter.EasSerializer;
import com.android.exchange.adapter.EasSyncAdapter;
import com.android.exchange.adapter.EasParser.EasParserException;
import com.android.exchange.adapter.AbstractSyncAdapter;
import com.android.exchange.adapter.ContactsSyncAdapter;
import com.android.exchange.adapter.EmailSyncAdapter;
import com.android.exchange.adapter.FolderSyncParser;
import com.android.exchange.adapter.PingParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.exchange.adapter.Parser.EasParserException;
import com.android.exchange.utility.Base64;
import org.apache.http.HttpEntity;
@ -47,7 +48,6 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.os.RemoteException;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -79,8 +79,8 @@ public class EasSyncService extends InteractiveSyncService {
Mailbox.SYNC_INTERVAL + '=' + Account.CHECK_INTERVAL_PING;
private static final String AND_FREQUENCY_PING_PUSH_AND_NOT_ACCOUNT_MAILBOX = " AND " +
MailboxColumns.SYNC_INTERVAL + " IN (" + Account.CHECK_INTERVAL_PING +
',' + Account.CHECK_INTERVAL_PUSH + ") AND " + MailboxColumns.SERVER_ID + "!=\"" +
Eas.ACCOUNT_MAILBOX + '\"';
',' + Account.CHECK_INTERVAL_PUSH + ") AND " + MailboxColumns.TYPE + "!=\"" +
Mailbox.TYPE_EAS_ACCOUNT_MAILBOX + '\"';
static private final int CHUNK_SIZE = 16 * 1024;
@ -89,7 +89,7 @@ public class EasSyncService extends InteractiveSyncService {
public Double mProtocolVersionDouble;
static String mDeviceId = null;
static String mDeviceType = "Android";
EasSyncAdapter mTarget;
AbstractSyncAdapter mTarget;
String mAuthString = null;
String mCmdString = null;
String mVersions;
@ -148,12 +148,10 @@ public class EasSyncService extends InteractiveSyncService {
public void validateAccount(String hostAddress, String userName, String password, int port,
boolean ssl, Context context) throws MessagingException {
try {
if (Eas.USER_DEBUG) {
userLog("Testing EAS: " + hostAddress + ", " + userName + ", ssl = " + ssl);
}
EasSerializer s = new EasSerializer();
s.start("FolderSync").start("FolderSyncKey").text("0").end("FolderSyncKey")
.end("FolderSync").end();
userLog("Testing EAS: " + hostAddress + ", " + userName + ", ssl = " + ssl);
Serializer s = new Serializer();
s.start(Tags.FOLDER_FOLDER_SYNC).start(Tags.FOLDER_SYNC_KEY).text("0")
.end().end().done();
EasSyncService svc = new EasSyncService("%TestAccount%");
svc.mHostAddress = hostAddress;
svc.mUserName = userName;
@ -286,9 +284,6 @@ public class EasSyncService extends InteractiveSyncService {
HttpEntity e = res.getEntity();
int len = (int)e.getContentLength();
String type = e.getContentType().getValue();
if (Eas.TEST_DEBUG) {
Log.v(TAG, "Attachment code: " + status + ", Length: " + len + ", Type: " + type);
}
InputStream is = res.getEntity().getContent();
File f = (req.destination != null)
? new File(req.destination)
@ -473,9 +468,9 @@ public class EasSyncService extends InteractiveSyncService {
}
while (!mStop) {
EasSerializer s = new EasSerializer();
s.start("FolderSync").start("FolderSyncKey").text(mAccount.mSyncKey).end(
"FolderSyncKey").end("FolderSync").end();
Serializer s = new Serializer();
s.start(Tags.FOLDER_FOLDER_SYNC).start(Tags.FOLDER_SYNC_KEY)
.text(mAccount.mSyncKey).end().end().done();
uc = sendEASPostCommand("FolderSync", s.toString());
code = uc.getResponseCode();
if (code == HttpURLConnection.HTTP_OK) {
@ -485,7 +480,7 @@ public class EasSyncService extends InteractiveSyncService {
if (len > 0) {
InputStream is = uc.getInputStream();
// Returns true if we need to sync again
if (new EasFolderSyncParser(is, this).parse()) {
if (new FolderSyncParser(is, this).parse()) {
continue;
}
}
@ -535,13 +530,14 @@ public class EasSyncService extends InteractiveSyncService {
void runPingLoop() throws IOException, StaleFolderListException {
// Do push for all sync services here
long endTime = System.currentTimeMillis() + (30*MINS);
long lastPingTime = 0;
while (System.currentTimeMillis() < endTime) {
// Count of pushable mailboxes
int pushCount = 0;
// Count of mailboxes that can be pushed right now
int canPushCount = 0;
EasSerializer s = new EasSerializer();
Serializer s = new Serializer();
HttpURLConnection uc;
int code;
Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION,
@ -562,15 +558,16 @@ public class EasSyncService extends InteractiveSyncService {
}
if (canPushCount++ == 0) {
// Initialize the Ping command
s.start("Ping").data("HeartbeatInterval", "900").start("PingFolders");
s.start(Tags.PING_PING).data(Tags.PING_HEARTBEAT_INTERVAL, "900")
.start(Tags.PING_FOLDERS);
}
// When we're ready for Calendar/Contacts, we will check folder type
// TODO Save Calendar and Contacts!! Mark as not visible!
String folderClass = getTargetCollectionClassFromCursor(c);
s.start("PingFolder")
.data("PingId", c.getString(Mailbox.CONTENT_SERVER_ID_COLUMN))
.data("PingClass", folderClass)
.end("PingFolder");
s.start(Tags.PING_FOLDER)
.data(Tags.PING_ID, c.getString(Mailbox.CONTENT_SERVER_ID_COLUMN))
.data(Tags.PING_CLASS, folderClass)
.end();
userLog("Ping ready for: " + folderClass + ", " +
c.getString(Mailbox.CONTENT_SERVER_ID_COLUMN) + " (" +
c.getString(Mailbox.CONTENT_DISPLAY_NAME_COLUMN) + ')');
@ -585,7 +582,18 @@ public class EasSyncService extends InteractiveSyncService {
if (canPushCount > 0 && (canPushCount == pushCount)) {
// If we have some number that are ready for push, send Ping to the server
s.end("PingFolders").end("Ping").end();
s.end().end().done();
long time = System.currentTimeMillis();
long timeSinceLastPing = time - lastPingTime;
if (timeSinceLastPing < 30*SECS) {
try {
userLog("Waiting to send ping...");
Thread.sleep(30*SECS - timeSinceLastPing);
} catch (InterruptedException e) {
// No need for action
}
}
uc = sendEASPostCommand("Ping", s.toString());
Thread.currentThread().setName(mAccount.mDisplayName + ": Ping");
userLog("Sending ping, timeout: " + uc.getReadTimeout() / 1000 + "s");
@ -599,7 +607,9 @@ public class EasSyncService extends InteractiveSyncService {
if (encoding == null) {
int len = uc.getHeaderFieldInt("Content-Length", 0);
if (len > 0) {
parsePingResult(uc, mContentResolver);
if (parsePingResult(uc, mContentResolver) > 0) {
lastPingTime = time;
}
} else {
// This implies a connection issue that we can't handle
throw new IOException();
@ -633,9 +643,9 @@ public class EasSyncService extends InteractiveSyncService {
}
}
void parsePingResult(HttpURLConnection uc, ContentResolver cr)
private int parsePingResult(HttpURLConnection uc, ContentResolver cr)
throws IOException, StaleFolderListException {
EasPingParser pp = new EasPingParser(uc.getInputStream(), this);
PingParser pp = new PingParser(uc.getInputStream(), this);
if (pp.parse()) {
// True indicates some mailboxes need syncing...
// syncList has the serverId's of the mailboxes...
@ -654,6 +664,7 @@ public class EasSyncService extends InteractiveSyncService {
}
}
}
return pp.getSyncList().size();
}
ByteArrayInputStream readResponse(HttpURLConnection uc) throws IOException {
@ -738,7 +749,7 @@ public class EasSyncService extends InteractiveSyncService {
*
* @param target, an EasMailbox, EasContacts, or EasCalendar object
*/
public void sync(EasSyncAdapter target) throws IOException {
public void sync(AbstractSyncAdapter target) throws IOException {
mTarget = target;
Mailbox mailbox = target.mMailbox;
@ -762,7 +773,7 @@ public class EasSyncService extends InteractiveSyncService {
}
}
EasSerializer s = new EasSerializer();
Serializer s = new Serializer();
if (mailbox.mSyncKey == null) {
userLog("Mailbox syncKey RESET");
mailbox.mSyncKey = "0";
@ -770,19 +781,19 @@ public class EasSyncService extends InteractiveSyncService {
}
String className = target.getCollectionName();
userLog("Sending " + className + " syncKey: " + mailbox.mSyncKey);
s.start("Sync")
.start("Collections")
.start("Collection")
.data("Class", className)
.data("SyncKey", mailbox.mSyncKey)
.data("CollectionId", mailbox.mServerId)
.tag("DeletesAsMoves");
s.start(Tags.SYNC_SYNC)
.start(Tags.SYNC_COLLECTIONS)
.start(Tags.SYNC_COLLECTION)
.data(Tags.SYNC_CLASS, className)
.data(Tags.SYNC_SYNC_KEY, mailbox.mSyncKey)
.data(Tags.SYNC_COLLECTION_ID, mailbox.mServerId)
.tag(Tags.SYNC_DELETES_AS_MOVES);
// EAS doesn't like GetChanges if the syncKey is "0"; not documented
if (!mailbox.mSyncKey.equals("0")) {
s.tag("GetChanges");
s.tag(Tags.SYNC_GET_CHANGES);
}
s.data("WindowSize", WINDOW_SIZE);
s.data(Tags.SYNC_WINDOW_SIZE, WINDOW_SIZE);
boolean options = false;
if (!className.equals("Contacts")) {
// Set the lookback appropriately (EAS calls this a "filter")
@ -813,30 +824,32 @@ public class EasSyncService extends InteractiveSyncService {
break;
}
}
s.start("Options").data("FilterType", filter);
if (mProtocolVersionDouble < 12.0) {
s.data("Truncation", "7");
}
s.start(Tags.SYNC_OPTIONS).data(Tags.SYNC_FILTER_TYPE, filter);
// No truncation in this version
//if (mProtocolVersionDouble < 12.0) {
// s.data(Tags.SYNC_TRUNCATION, "7");
//}
options = true;
}
if (mProtocolVersionDouble >= 12.0) {
if (!options) {
options = true;
s.start("Options");
s.start(Tags.SYNC_OPTIONS);
}
s.start("BodyPreference")
.data("BodyPreferenceType", Eas.BODY_PREFERENCE_HTML)
.data("BodyPreferenceTruncationSize", Eas.DEFAULT_BODY_TRUNCATION_SIZE)
.end("BodyPreference");
s.start(Tags.BASE_BODY_PREFERENCE)
.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_HTML)
// No truncation in this version
//.data(Tags.BASE_TRUNCATION_SIZE, Eas.DEFAULT_BODY_TRUNCATION_SIZE)
.end();
}
if (options) {
s.end("Options");
s.end();
}
// Send our changes up to the server
target.sendLocalChanges(s, this);
s.end("Collection").end("Collections").end("Sync").end();
s.end().end().end().done();
HttpURLConnection uc = sendEASPostCommand("Sync", s.toString());
int code = uc.getResponseCode();
if (code == HttpURLConnection.HTTP_OK) {
@ -887,18 +900,18 @@ public class EasSyncService extends InteractiveSyncService {
try {
if (mMailbox == null || mAccount == null) {
return;
} else if (mMailbox.mServerId.equals(Eas.ACCOUNT_MAILBOX)) {
} else if (mMailbox.mType == Mailbox.TYPE_EAS_ACCOUNT_MAILBOX) {
accountMailbox = true;
runAccountMailbox();
} else {
EasSyncAdapter target;
AbstractSyncAdapter target;
mAccount = Account.restoreAccountWithId(mContext, mAccount.mId);
mProtocolVersion = mAccount.mProtocolVersion;
mProtocolVersionDouble = Double.parseDouble(mProtocolVersion);
if (mMailbox.mType == Mailbox.TYPE_CONTACTS)
target = new EasContactsSyncAdapter(mMailbox, this);
target = new ContactsSyncAdapter(mMailbox, this);
else {
target = new EasEmailSyncAdapter(mMailbox, this);
target = new EmailSyncAdapter(mMailbox, this);
}
// We loop here because someone might have put a request in while we were syncing
// and we've missed that opportunity...

View File

@ -23,11 +23,9 @@ import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Attachment;
import com.android.email.provider.EmailContent.HostAuth;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.email.provider.EmailContent.MailboxColumns;
import com.android.email.provider.EmailContent.Message;
import com.android.email.provider.EmailContent.MessageColumns;
import com.android.email.provider.EmailContent.SyncColumns;
import com.android.exchange.adapter.EasOutboxService;
import android.app.AlarmManager;
import android.app.PendingIntent;
@ -175,10 +173,10 @@ public class SyncManager extends Service implements Runnable {
}
public void updateFolderList(long accountId) throws RemoteException {
Cursor c = getContentResolver().query(Mailbox.CONTENT_URI,
Mailbox.CONTENT_PROJECTION, MailboxColumns.ACCOUNT_KEY + "=? AND " +
MailboxColumns.SERVER_ID + "=?",
new String[] {Long.toString(accountId), Eas.ACCOUNT_MAILBOX}, null);
// Cursor c = getContentResolver().query(Mailbox.CONTENT_URI,
// Mailbox.CONTENT_PROJECTION, MailboxColumns.ACCOUNT_KEY + "=? AND " +
// MailboxColumns.SERVER_ID + "=?",
// new String[] {Long.toString(accountId), Eas.ACCOUNT_MAILBOX}, null);
sCallbackProxy.syncMailboxListStatus(accountId, EmailServiceStatus.IN_PROGRESS, 0);
sCallbackProxy.syncMailboxListStatus(accountId, EmailServiceStatus.SUCCESS, 0);
// TODO Remove previous two lines; reimplement what's below (this is bug #2026451)
@ -199,7 +197,7 @@ public class SyncManager extends Service implements Runnable {
}
public void setLogging(boolean on) throws RemoteException {
Eas.USER_DEBUG = on;
Eas.setUserDebug(on);
}
public void loadMore(long messageId) throws RemoteException {
@ -338,9 +336,9 @@ public class SyncManager extends Service implements Runnable {
Account acct = Account.restoreAccountWithId(getContext(), acctId);
Mailbox main = new Mailbox();
main.mDisplayName = Eas.ACCOUNT_MAILBOX;
main.mServerId = Eas.ACCOUNT_MAILBOX;
main.mServerId = Eas.ACCOUNT_MAILBOX + System.nanoTime();
main.mAccountKey = acct.mId;
main.mType = Mailbox.TYPE_NOT_EMAIL;
main.mType = Mailbox.TYPE_EAS_ACCOUNT_MAILBOX;
main.mSyncInterval = Account.CHECK_INTERVAL_PUSH;
main.mFlagVisible = false;
main.save(getContext());
@ -466,7 +464,7 @@ public class SyncManager extends Service implements Runnable {
}
public void log(String str) {
if (Eas.USER_DEBUG) {
if (Eas.USER_LOG) {
Log.d(TAG, str);
}
}
@ -706,8 +704,17 @@ public class SyncManager extends Service implements Runnable {
public void run() {
mStop = false;
// If we're really debugging, turn on all logging
if (Eas.DEBUG) {
Eas.PARSER_LOG = true;
Eas.USER_LOG = true;
}
runAwake(-1);
// Set up our observers; we need them to know when to start/stop various syncs based
// on the insert/delete/update of mailboxes and accounts
// We also observe synced messages to trigger upsyncs at the appropriate time
ContentResolver resolver = getContentResolver();
resolver.registerContentObserver(Account.CONTENT_URI, false, mAccountObserver);
resolver.registerContentObserver(Mailbox.CONTENT_URI, false, mMailboxObserver);

View File

@ -27,12 +27,12 @@ import java.io.IOException;
* Parent class of all sync adapters (EasMailbox, EasCalendar, and EasContacts)
*
*/
public abstract class EasSyncAdapter {
public abstract class AbstractSyncAdapter {
public Mailbox mMailbox;
public EasSyncService mService;
// Create the data for local changes that need to be sent up to the server
public abstract boolean sendLocalChanges(EasSerializer s, EasSyncService service)
public abstract boolean sendLocalChanges(Serializer s, EasSyncService service)
throws IOException;
// Parse incoming data from the EAS server, creating, modifying, and deleting objects as
// required through the EmailProvider
@ -42,7 +42,7 @@ public abstract class EasSyncAdapter {
public abstract String getCollectionName();
public abstract void cleanup(EasSyncService service);
public EasSyncAdapter(Mailbox mailbox, EasSyncService service) {
public AbstractSyncAdapter(Mailbox mailbox, EasSyncService service) {
mMailbox = mailbox;
mService = service;
}

View File

@ -27,9 +27,9 @@ import java.io.IOException;
* Sync adapter class for EAS calendars
*
*/
public class EasCalendarSyncAdapter extends EasSyncAdapter {
public class CalendarSyncAdapter extends AbstractSyncAdapter {
public EasCalendarSyncAdapter(Mailbox mailbox, EasSyncService service) {
public CalendarSyncAdapter(Mailbox mailbox, EasSyncService service) {
super(mailbox, service);
}
@ -45,7 +45,7 @@ public class EasCalendarSyncAdapter extends EasSyncAdapter {
}
@Override
public boolean sendLocalChanges(EasSerializer s, EasSyncService service) throws IOException {
public boolean sendLocalChanges(Serializer s, EasSyncService service) throws IOException {
// TODO Auto-generated method stub
return false;
}

View File

@ -56,7 +56,7 @@ import java.util.ArrayList;
* Sync adapter for EAS Contacts
*
*/
public class EasContactsSyncAdapter extends EasSyncAdapter {
public class ContactsSyncAdapter extends AbstractSyncAdapter {
private static final String TAG = "EasContactsSyncAdapter";
private static final String SERVER_ID_SELECTION = RawContacts.SOURCE_ID + "=?";
@ -82,7 +82,7 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();
public EasContactsSyncAdapter(Mailbox mailbox, EasSyncService service) {
public ContactsSyncAdapter(Mailbox mailbox, EasSyncService service) {
super(mailbox, service);
}
@ -105,7 +105,7 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
public static final String EXTRAS = "data2";
}
class EasContactsSyncParser extends EasContentParser {
class EasContactsSyncParser extends ContentParser {
String[] mBindArgument = new String[1];
String mMailboxIdAsString;
@ -114,13 +114,27 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
public EasContactsSyncParser(InputStream in, EasSyncService service) throws IOException {
super(in, service);
mAccountUri = uriWithAccount(RawContacts.CONTENT_URI);
setDebug(false); // DON'T CHECK IN WITH THIS UNCOMMENTED
}
@Override
public void wipe() {
// TODO Uncomment when the new provider works with this
//mContentResolver.delete(mAccountUri, null, null);
// TODO Use the bulk delete when the CP supports it
// mContentResolver.delete(mAccountUri.buildUpon()
// .appendQueryParameter(ContactsContract.RawContacts.DELETE_PERMANENTLY, "true")
// .build(), null, null);
Cursor c = mContentResolver.query(mAccountUri, new String[] {"_id"}, null, null, null);
try {
while (c.moveToNext()) {
long id = c.getLong(0);
mContentResolver.delete(ContentUris
.withAppendedId(mAccountUri, id)
.buildUpon().appendQueryParameter(
ContactsContract.RawContacts.DELETE_PERMANENTLY, "true")
.build(), null, null);
}
} finally {
c.close();
}
}
void saveExtraData (StringBuilder extras, int tag) throws IOException {
@ -160,157 +174,157 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
StringBuilder extraData = new StringBuilder(1024);
while (nextTag(EasTags.SYNC_APPLICATION_DATA) != END) {
while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
switch (tag) {
case EasTags.CONTACTS_FIRST_NAME:
case Tags.CONTACTS_FIRST_NAME:
firstName = getValue();
break;
case EasTags.CONTACTS_LAST_NAME:
case Tags.CONTACTS_LAST_NAME:
lastName = getValue();
break;
case EasTags.CONTACTS_COMPANY_NAME:
case Tags.CONTACTS_COMPANY_NAME:
companyName = getValue();
break;
case EasTags.CONTACTS_JOB_TITLE:
case Tags.CONTACTS_JOB_TITLE:
title = getValue();
break;
case EasTags.CONTACTS_EMAIL1_ADDRESS:
case Tags.CONTACTS_EMAIL1_ADDRESS:
ops.addEmail(entity, TYPE_EMAIL1, getValue());
break;
case EasTags.CONTACTS_EMAIL2_ADDRESS:
case Tags.CONTACTS_EMAIL2_ADDRESS:
ops.addEmail(entity, TYPE_EMAIL2, getValue());
break;
case EasTags.CONTACTS_EMAIL3_ADDRESS:
case Tags.CONTACTS_EMAIL3_ADDRESS:
ops.addEmail(entity, TYPE_EMAIL3, getValue());
break;
case EasTags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER:
case Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER:
ops.addPhone(entity, TYPE_WORK2, getValue());
break;
case EasTags.CONTACTS_BUSINESS_TELEPHONE_NUMBER:
case Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER:
ops.addPhone(entity, Phone.TYPE_WORK, getValue());
break;
case EasTags.CONTACTS2_MMS:
case Tags.CONTACTS2_MMS:
ops.addPhone(entity, TYPE_MMS, getValue());
break;
case EasTags.CONTACTS_BUSINESS_FAX_NUMBER:
case Tags.CONTACTS_BUSINESS_FAX_NUMBER:
ops.addPhone(entity, Phone.TYPE_FAX_WORK, getValue());
break;
case EasTags.CONTACTS2_COMPANY_MAIN_PHONE:
case Tags.CONTACTS2_COMPANY_MAIN_PHONE:
ops.addPhone(entity, TYPE_COMPANY_MAIN, getValue());
break;
case EasTags.CONTACTS_HOME_FAX_NUMBER:
case Tags.CONTACTS_HOME_FAX_NUMBER:
ops.addPhone(entity, Phone.TYPE_FAX_HOME, getValue());
break;
case EasTags.CONTACTS_HOME_TELEPHONE_NUMBER:
case Tags.CONTACTS_HOME_TELEPHONE_NUMBER:
ops.addPhone(entity, Phone.TYPE_HOME, getValue());
break;
case EasTags.CONTACTS_HOME2_TELEPHONE_NUMBER:
case Tags.CONTACTS_HOME2_TELEPHONE_NUMBER:
ops.addPhone(entity, TYPE_HOME2, getValue());
break;
case EasTags.CONTACTS_MOBILE_TELEPHONE_NUMBER:
case Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER:
ops.addPhone(entity, Phone.TYPE_MOBILE, getValue());
break;
case EasTags.CONTACTS_CAR_TELEPHONE_NUMBER:
case Tags.CONTACTS_CAR_TELEPHONE_NUMBER:
ops.addPhone(entity, TYPE_CAR, getValue());
break;
case EasTags.CONTACTS_RADIO_TELEPHONE_NUMBER:
case Tags.CONTACTS_RADIO_TELEPHONE_NUMBER:
ops.addPhone(entity, TYPE_RADIO, getValue());
break;
case EasTags.CONTACTS_PAGER_NUMBER:
case Tags.CONTACTS_PAGER_NUMBER:
ops.addPhone(entity, Phone.TYPE_PAGER, getValue());
break;
case EasTags.CONTACTS2_IM_ADDRESS:
case Tags.CONTACTS2_IM_ADDRESS:
ops.addIm(entity, TYPE_IM1, getValue());
break;
case EasTags.CONTACTS2_IM_ADDRESS_2:
case Tags.CONTACTS2_IM_ADDRESS_2:
ops.addIm(entity, TYPE_IM2, getValue());
break;
case EasTags.CONTACTS2_IM_ADDRESS_3:
case Tags.CONTACTS2_IM_ADDRESS_3:
ops.addIm(entity, TYPE_IM3, getValue());
break;
case EasTags.CONTACTS_BUSINESS_ADDRESS_CITY:
case Tags.CONTACTS_BUSINESS_ADDRESS_CITY:
work.city = getValue();
break;
case EasTags.CONTACTS_BUSINESS_ADDRESS_COUNTRY:
case Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY:
work.country = getValue();
break;
case EasTags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE:
case Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE:
work.code = getValue();
break;
case EasTags.CONTACTS_BUSINESS_ADDRESS_STATE:
case Tags.CONTACTS_BUSINESS_ADDRESS_STATE:
work.state = getValue();
break;
case EasTags.CONTACTS_BUSINESS_ADDRESS_STREET:
case Tags.CONTACTS_BUSINESS_ADDRESS_STREET:
work.street = getValue();
break;
case EasTags.CONTACTS_HOME_ADDRESS_CITY:
case Tags.CONTACTS_HOME_ADDRESS_CITY:
home.city = getValue();
break;
case EasTags.CONTACTS_HOME_ADDRESS_COUNTRY:
case Tags.CONTACTS_HOME_ADDRESS_COUNTRY:
home.country = getValue();
break;
case EasTags.CONTACTS_HOME_ADDRESS_POSTAL_CODE:
case Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE:
home.code = getValue();
break;
case EasTags.CONTACTS_HOME_ADDRESS_STATE:
case Tags.CONTACTS_HOME_ADDRESS_STATE:
home.state = getValue();
break;
case EasTags.CONTACTS_HOME_ADDRESS_STREET:
case Tags.CONTACTS_HOME_ADDRESS_STREET:
home.street = getValue();
break;
case EasTags.CONTACTS_OTHER_ADDRESS_CITY:
case Tags.CONTACTS_OTHER_ADDRESS_CITY:
other.city = getValue();
break;
case EasTags.CONTACTS_OTHER_ADDRESS_COUNTRY:
case Tags.CONTACTS_OTHER_ADDRESS_COUNTRY:
other.country = getValue();
break;
case EasTags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE:
case Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE:
other.code = getValue();
break;
case EasTags.CONTACTS_OTHER_ADDRESS_STATE:
case Tags.CONTACTS_OTHER_ADDRESS_STATE:
other.state = getValue();
break;
case EasTags.CONTACTS_OTHER_ADDRESS_STREET:
case Tags.CONTACTS_OTHER_ADDRESS_STREET:
other.street = getValue();
break;
case EasTags.CONTACTS_CHILDREN:
case Tags.CONTACTS_CHILDREN:
childrenParser(extraData);
break;
case EasTags.CONTACTS_CATEGORIES:
case Tags.CONTACTS_CATEGORIES:
categoriesParser(extraData);
break;
// TODO We'll add this later
case EasTags.CONTACTS_PICTURE:
case Tags.CONTACTS_PICTURE:
getValue();
break;
// All tags that we don't use (except for a few like picture and body) need to
// be saved, even if we're not using them. Otherwise, when we upload changes,
// those items will be deleted back on the server.
case EasTags.CONTACTS_ANNIVERSARY:
case EasTags.CONTACTS_ASSISTANT_NAME:
case EasTags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER:
case EasTags.CONTACTS_BIRTHDAY:
case EasTags.CONTACTS_DEPARTMENT:
case EasTags.CONTACTS_FILE_AS:
case EasTags.CONTACTS_TITLE:
case EasTags.CONTACTS_MIDDLE_NAME:
case EasTags.CONTACTS_OFFICE_LOCATION:
case EasTags.CONTACTS_SPOUSE:
case EasTags.CONTACTS_SUFFIX:
case EasTags.CONTACTS_WEBPAGE:
case EasTags.CONTACTS_YOMI_COMPANY_NAME:
case EasTags.CONTACTS_YOMI_FIRST_NAME:
case EasTags.CONTACTS_YOMI_LAST_NAME:
case EasTags.CONTACTS_COMPRESSED_RTF:
case EasTags.CONTACTS2_CUSTOMER_ID:
case EasTags.CONTACTS2_GOVERNMENT_ID:
case EasTags.CONTACTS2_MANAGER_NAME:
case EasTags.CONTACTS2_ACCOUNT_NAME:
case EasTags.CONTACTS2_NICKNAME:
case Tags.CONTACTS_ANNIVERSARY:
case Tags.CONTACTS_ASSISTANT_NAME:
case Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER:
case Tags.CONTACTS_BIRTHDAY:
case Tags.CONTACTS_DEPARTMENT:
case Tags.CONTACTS_FILE_AS:
case Tags.CONTACTS_TITLE:
case Tags.CONTACTS_MIDDLE_NAME:
case Tags.CONTACTS_OFFICE_LOCATION:
case Tags.CONTACTS_SPOUSE:
case Tags.CONTACTS_SUFFIX:
case Tags.CONTACTS_WEBPAGE:
case Tags.CONTACTS_YOMI_COMPANY_NAME:
case Tags.CONTACTS_YOMI_FIRST_NAME:
case Tags.CONTACTS_YOMI_LAST_NAME:
case Tags.CONTACTS_COMPRESSED_RTF:
case Tags.CONTACTS2_CUSTOMER_ID:
case Tags.CONTACTS2_GOVERNMENT_ID:
case Tags.CONTACTS2_MANAGER_NAME:
case Tags.CONTACTS2_ACCOUNT_NAME:
case Tags.CONTACTS2_NICKNAME:
saveExtraData(extraData, tag);
break;
default:
@ -356,9 +370,9 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
}
private void categoriesParser(StringBuilder extras) throws IOException {
while (nextTag(EasTags.CONTACTS_CATEGORIES) != END) {
while (nextTag(Tags.CONTACTS_CATEGORIES) != END) {
switch (tag) {
case EasTags.CONTACTS_CATEGORY:
case Tags.CONTACTS_CATEGORY:
saveExtraData(extras, tag);
default:
skipTag();
@ -367,9 +381,9 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
}
private void childrenParser(StringBuilder extras) throws IOException {
while (nextTag(EasTags.CONTACTS_CHILDREN) != END) {
while (nextTag(Tags.CONTACTS_CHILDREN) != END) {
switch (tag) {
case EasTags.CONTACTS_CHILD:
case Tags.CONTACTS_CHILD:
saveExtraData(extras, tag);
default:
skipTag();
@ -379,12 +393,12 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
public void addParser(ContactOperations ops) throws IOException {
String serverId = null;
while (nextTag(EasTags.SYNC_ADD) != END) {
while (nextTag(Tags.SYNC_ADD) != END) {
switch (tag) {
case EasTags.SYNC_SERVER_ID: // same as
case Tags.SYNC_SERVER_ID: // same as
serverId = getValue();
break;
case EasTags.SYNC_APPLICATION_DATA:
case Tags.SYNC_APPLICATION_DATA:
addData(serverId, ops, null);
break;
default:
@ -400,9 +414,9 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
}
public void deleteParser(ContactOperations ops) throws IOException {
while (nextTag(EasTags.SYNC_DELETE) != END) {
while (nextTag(Tags.SYNC_DELETE) != END) {
switch (tag) {
case EasTags.SYNC_SERVER_ID:
case Tags.SYNC_SERVER_ID:
String serverId = getValue();
// Find the message in this mailbox with the given serverId
Cursor c = getServerIdCursor(serverId);
@ -439,9 +453,9 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
public void changeParser(ContactOperations ops) throws IOException {
String serverId = null;
Entity entity = null;
while (nextTag(EasTags.SYNC_CHANGE) != END) {
while (nextTag(Tags.SYNC_CHANGE) != END) {
switch (tag) {
case EasTags.SYNC_SERVER_ID:
case Tags.SYNC_SERVER_ID:
serverId = getValue();
Cursor c = getServerIdCursor(serverId);
try {
@ -463,7 +477,7 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
c.close();
}
break;
case EasTags.SYNC_APPLICATION_DATA:
case Tags.SYNC_APPLICATION_DATA:
addData(serverId, ops, entity);
break;
default:
@ -475,12 +489,12 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
@Override
public void commandsParser() throws IOException {
ContactOperations ops = new ContactOperations();
while (nextTag(EasTags.SYNC_COMMANDS) != END) {
if (tag == EasTags.SYNC_ADD) {
while (nextTag(Tags.SYNC_COMMANDS) != END) {
if (tag == Tags.SYNC_ADD) {
addParser(ops);
} else if (tag == EasTags.SYNC_DELETE) {
} else if (tag == Tags.SYNC_DELETE) {
deleteParser(ops);
} else if (tag == EasTags.SYNC_CHANGE) {
} else if (tag == Tags.SYNC_CHANGE) {
changeParser(ops);
} else
skipTag();
@ -588,8 +602,13 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
}
public void delete(long id) {
add(ContentProviderOperation.newDelete(ContentUris
.withAppendedId(RawContacts.CONTENT_URI, id)).build());
add(ContentProviderOperation
.newDelete(ContentUris.withAppendedId(RawContacts.CONTENT_URI, id)
.buildUpon()
.appendQueryParameter(ContactsContract.RawContacts.DELETE_PERMANENTLY,
"true")
.build())
.build());
}
public void execute() {
@ -850,41 +869,41 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
return "Contacts";
}
private void sendEmail(EasSerializer s, ContentValues cv) throws IOException {
private void sendEmail(Serializer s, ContentValues cv) throws IOException {
String value = cv.getAsString(Email.DATA);
switch (cv.getAsInteger(Email.TYPE)) {
case TYPE_EMAIL1:
s.data("Email1Address", value);
s.data(Tags.CONTACTS_EMAIL1_ADDRESS, value);
break;
case TYPE_EMAIL2:
s.data("Email2Address", value);
s.data(Tags.CONTACTS_EMAIL2_ADDRESS, value);
break;
case TYPE_EMAIL3:
s.data("Email3Address", value);
s.data(Tags.CONTACTS_EMAIL3_ADDRESS, value);
break;
default:
break;
}
}
private void sendIm(EasSerializer s, ContentValues cv) throws IOException {
private void sendIm(Serializer s, ContentValues cv) throws IOException {
String value = cv.getAsString(Email.DATA);
switch (cv.getAsInteger(Email.TYPE)) {
case TYPE_IM1:
s.data("IMAddress", value);
s.data(Tags.CONTACTS2_IM_ADDRESS, value);
break;
case TYPE_IM2:
s.data("IMAddress2", value);
s.data(Tags.CONTACTS2_IM_ADDRESS_2, value);
break;
case TYPE_IM3:
s.data("IMAddress3", value);
s.data(Tags.CONTACTS2_IM_ADDRESS_3, value);
break;
default:
break;
}
}
private void sendOnePostal(EasSerializer s, ContentValues cv, String[] fieldNames)
private void sendOnePostal(Serializer s, ContentValues cv, int[] fieldNames)
throws IOException{
if (cv.containsKey(StructuredPostal.CITY)) {
s.data(fieldNames[0], cv.getAsString(StructuredPostal.CITY));
@ -903,88 +922,96 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
}
}
private void sendStructuredPostal(EasSerializer s, ContentValues cv) throws IOException {
private void sendStructuredPostal(Serializer s, ContentValues cv) throws IOException {
switch (cv.getAsInteger(StructuredPostal.TYPE)) {
case StructuredPostal.TYPE_HOME:
sendOnePostal(s, cv, new String[] {"HomeAddressCity", "HomeAddressCountry",
"HomeAddressPostalCode", "HomeAddressState", "HomeAddressStreet"});
sendOnePostal(s, cv, new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY,
Tags.CONTACTS_HOME_ADDRESS_COUNTRY,
Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE,
Tags.CONTACTS_HOME_ADDRESS_STATE,
Tags.CONTACTS_HOME_ADDRESS_STREET});
break;
case StructuredPostal.TYPE_WORK:
sendOnePostal(s, cv, new String[] {"BusinessAddressCity", "BusinessAddressCountry",
"BusinessAddressPostalCode", "BusinessAddressState",
"BusinessAddressStreet"});
sendOnePostal(s, cv, new int[] {Tags.CONTACTS_BUSINESS_ADDRESS_CITY,
Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY,
Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE,
Tags.CONTACTS_BUSINESS_ADDRESS_STATE,
Tags.CONTACTS_BUSINESS_ADDRESS_STREET});
break;
case StructuredPostal.TYPE_OTHER:
sendOnePostal(s, cv, new String[] {"OtherAddressCity", "OtherAddressCountry",
"OtherAddressPostalCode", "OtherAddressState", "OtherAddressStreet"});
sendOnePostal(s, cv, new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY,
Tags.CONTACTS_OTHER_ADDRESS_COUNTRY,
Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE,
Tags.CONTACTS_OTHER_ADDRESS_STATE,
Tags.CONTACTS_OTHER_ADDRESS_STREET});
break;
default:
break;
}
}
private void sendStructuredName(EasSerializer s, ContentValues cv) throws IOException {
private void sendStructuredName(Serializer s, ContentValues cv) throws IOException {
if (cv.containsKey(StructuredName.FAMILY_NAME)) {
s.data("LastName", cv.getAsString(StructuredName.FAMILY_NAME));
s.data(Tags.CONTACTS_LAST_NAME, cv.getAsString(StructuredName.FAMILY_NAME));
}
if (cv.containsKey(StructuredName.GIVEN_NAME)) {
s.data("FirstName", cv.getAsString(StructuredName.GIVEN_NAME));
s.data(Tags.CONTACTS_FIRST_NAME, cv.getAsString(StructuredName.GIVEN_NAME));
}
}
private void sendOrganization(EasSerializer s, ContentValues cv) throws IOException {
private void sendOrganization(Serializer s, ContentValues cv) throws IOException {
if (cv.containsKey(Organization.TITLE)) {
s.data("JobTitle", cv.getAsString(Organization.TITLE));
s.data(Tags.CONTACTS_JOB_TITLE, cv.getAsString(Organization.TITLE));
}
if (cv.containsKey(Organization.COMPANY)) {
s.data("CompanyName", cv.getAsString(Organization.COMPANY));
s.data(Tags.CONTACTS_COMPANY_NAME, cv.getAsString(Organization.COMPANY));
}
}
private void sendPhone(EasSerializer s, ContentValues cv) throws IOException {
private void sendPhone(Serializer s, ContentValues cv) throws IOException {
String value = cv.getAsString(Phone.NUMBER);
switch (cv.getAsInteger(Phone.TYPE)) {
case TYPE_WORK2:
s.data("Business2TelephoneNumber", value);
s.data(Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER, value);
break;
case Phone.TYPE_WORK:
s.data("BusinessTelephoneNumber", value);
s.data(Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER, value);
break;
case TYPE_MMS:
s.data("MMS", value);
s.data(Tags.CONTACTS2_MMS, value);
break;
case Phone.TYPE_FAX_WORK:
s.data("BusinessFaxNumber", value);
s.data(Tags.CONTACTS_BUSINESS_FAX_NUMBER, value);
break;
case TYPE_COMPANY_MAIN:
s.data("CompanyMainPhone", value);
s.data(Tags.CONTACTS2_COMPANY_MAIN_PHONE, value);
break;
case Phone.TYPE_HOME:
s.data("HomeTelephoneNumber", value);
s.data(Tags.CONTACTS_HOME_TELEPHONE_NUMBER, value);
break;
case TYPE_HOME2:
s.data("Home2TelephoneNumber", value);
s.data(Tags.CONTACTS_HOME2_TELEPHONE_NUMBER, value);
break;
case Phone.TYPE_MOBILE:
s.data("MobileTelephoneNumber", value);
s.data(Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER, value);
break;
case TYPE_CAR:
s.data("CarTelephoneNumber", value);
s.data(Tags.CONTACTS_CAR_TELEPHONE_NUMBER, value);
break;
case Phone.TYPE_PAGER:
s.data("PagerNumber", value);
s.data(Tags.CONTACTS_PAGER_NUMBER, value);
break;
case TYPE_RADIO:
s.data("RadioTelephoneNumber", value);
s.data(Tags.CONTACTS_RADIO_TELEPHONE_NUMBER, value);
break;
case Phone.TYPE_FAX_HOME:
s.data("HomeFaxNumber", value);
s.data(Tags.CONTACTS_HOME_FAX_NUMBER, value);
break;
case TYPE_EMAIL2:
s.data("Email2Address", value);
s.data(Tags.CONTACTS_EMAIL2_ADDRESS, value);
break;
case TYPE_EMAIL3:
s.data("Email3Address", value);
s.data(Tags.CONTACTS_EMAIL3_ADDRESS, value);
break;
default:
break;
@ -992,7 +1019,7 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
}
@Override
public boolean sendLocalChanges(EasSerializer s, EasSyncService service) throws IOException {
public boolean sendLocalChanges(Serializer s, EasSyncService service) throws IOException {
// First, let's find Contacts that have changed.
ContentResolver cr = service.mContentResolver;
Uri uri = RawContacts.CONTENT_URI.buildUpon()
@ -1000,10 +1027,13 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
.appendQueryParameter(RawContacts.ACCOUNT_TYPE, Eas.ACCOUNT_MANAGER_TYPE)
.build();
if (service.mMailbox.mSyncKey.equals("0")) {
return false;
}
try {
// Get them all atomically
//EntityIterator ei = cr.queryEntities(uri, RawContacts.DIRTY + "=1", null, null);
EntityIterator ei = cr.queryEntities(uri, null, null, null);
EntityIterator ei = cr.queryEntities(uri, RawContacts.DIRTY + "=1", null, null);
boolean first = true;
while (ei.hasNext()) {
Entity entity = ei.next();
@ -1011,10 +1041,11 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
ContentValues entityValues = entity.getEntityValues();
String serverId = entityValues.getAsString(RawContacts.SOURCE_ID);
if (first) {
s.start("Commands");
s.start(Tags.SYNC_COMMANDS);
first = false;
}
s.start("Change").data("ServerId", serverId).start("ApplicationData");
s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, serverId)
.start(Tags.SYNC_APPLICATION_DATA);
// Write out the data here
for (NamedContentValues ncv: entity.getSubValues()) {
ContentValues cv = ncv.values;
@ -1032,18 +1063,18 @@ public class EasContactsSyncAdapter extends EasSyncAdapter {
} else if (mimeType.equals(Im.CONTENT_ITEM_TYPE)) {
sendIm(s, cv);
} else if (mimeType.equals(Note.CONTENT_ITEM_TYPE)) {
// TODO Finish this...
} else if (mimeType.equals(Extras.CONTENT_ITEM_TYPE)) {
// TODO Finish this...
} else {
mService.userLog("Contacts upsync, unknown data: " + mimeType);
}
}
s.end("ApplicationData").end("Change");
s.end().end(); // ApplicationData & Change
mUpdatedIdList.add(entityValues.getAsLong(RawContacts._ID));
}
if (!first) {
s.end("Commands");
s.end(); // Commands
}
} catch (RemoteException e) {

View File

@ -35,19 +35,15 @@ import java.io.InputStream;
* Each subclass must implement a handful of methods that relate specifically to the data type
*
*/
public abstract class EasContentParser extends EasParser {
public abstract class ContentParser extends Parser {
EasSyncService mService;
Mailbox mMailbox;
Account mAccount;
Context mContext;
ContentResolver mContentResolver;
public EasContentParser(InputStream in, EasSyncService _service) throws IOException {
public ContentParser(InputStream in, EasSyncService _service) throws IOException {
super(in);
mService = _service;
mContext = mService.mContext;
@ -82,18 +78,19 @@ public abstract class EasContentParser extends EasParser {
* Sync keys and the more available flag are handled here, whereas specific data parsing
* is handled by abstract methods implemented for each data class (e.g. Email, Contacts, etc.)
*/
@Override
public boolean parse() throws IOException {
int status;
boolean moreAvailable = false;
// If we're not at the top of the xml tree, throw an exception
if (nextTag(START_DOCUMENT) != EasTags.SYNC_SYNC) {
if (nextTag(START_DOCUMENT) != Tags.SYNC_SYNC) {
throw new IOException();
}
// Loop here through the remaining xml
while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
if (tag == EasTags.SYNC_COLLECTION || tag == EasTags.SYNC_COLLECTIONS) {
if (tag == Tags.SYNC_COLLECTION || tag == Tags.SYNC_COLLECTIONS) {
// Ignore these tags, since we've only got one collection syncing in this loop
} else if (tag == EasTags.SYNC_STATUS) {
} else if (tag == Tags.SYNC_STATUS) {
// Status = 1 is success; everything else is a failure
status = getValueInt();
if (status != 1) {
@ -111,13 +108,13 @@ public abstract class EasContentParser extends EasParser {
moreAvailable = true;
}
}
} else if (tag == EasTags.SYNC_COMMANDS) {
} else if (tag == Tags.SYNC_COMMANDS) {
commandsParser();
} else if (tag == EasTags.SYNC_RESPONSES) {
} else if (tag == Tags.SYNC_RESPONSES) {
responsesParser();
} else if (tag == EasTags.SYNC_MORE_AVAILABLE) {
} else if (tag == Tags.SYNC_MORE_AVAILABLE) {
moreAvailable = true;
} else if (tag == EasTags.SYNC_SYNC_KEY) {
} else if (tag == Tags.SYNC_SYNC_KEY) {
if (mMailbox.mSyncKey.equals("0"))
moreAvailable = true;
String newKey = getValue();

View File

@ -1,103 +0,0 @@
/*
* Copyright (C) 2008-2009 Marc Blank
* Licensed to The Android Open Source Project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.exchange.adapter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Hashtable;
/**
* This is a convenience class that simplifies the creation of Wbxml commands and allows
* multiple commands to be chained together.
*
* Each start command must pair with an end command; the values of all data fields are Strings. The
* methods here should be self-explanatory.
*
* Use toString() to obtain the output for the EAS server
*/
public class EasSerializer extends WbxmlSerializer {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
static Hashtable<String, Object> tagTable = null;
public EasSerializer() {
super();
try {
setOutput(byteStream, null);
// Lazy initialization of our tag tables, as created from EasTags
if (tagTable == null) {
String[][] pages = EasTags.pages;
for (int i = 0; i < pages.length; i++) {
String[] page = pages[i];
if (page.length > 0) {
setTagTable(i, page);
}
}
tagTable = getTagTable();
} else {
setTagTable(tagTable);
}
startDocument("UTF-8", false);
} catch (IOException e) {
e.printStackTrace();
}
}
public EasSerializer start(String tag) throws IOException {
startTag(null, tag);
return this;
}
public EasSerializer end(String tag) throws IOException {
endTag(null, tag);
return this;
}
public EasSerializer end() throws IOException {
endDocument();
return this;
}
public EasSerializer data(String tag, String value) throws IOException {
startTag(null, tag);
text(value);
endTag(null, tag);
return this;
}
public EasSerializer tag(String tag) throws IOException {
startTag(null, tag);
endTag(null, tag);
return this;
}
public EasSerializer text(String str) throws IOException {
super.text(str);
return this;
}
public ByteArrayOutputStream getByteStream() {
return byteStream;
}
public String toString() {
return byteStream.toString();
}
}

View File

@ -1,461 +0,0 @@
/*
* Copyright (C) 2008-2009 Marc Blank
* Licensed to The Android Open Source Project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.exchange.adapter;
/**
* The wbxml tags for EAS are all defined here.
*
* The static final int's, of the form <page>_<tag> = <constant> are used in parsing incoming
* responses from the server (i.e. EasParser and its subclasses).
*
* The array of String arrays is used to construct server requests with EasSerializer. One thing
* we might do eventually is to "precompile" these requests, in part, although they should be
* fairly fast to begin with (each tag requires one HashMap lookup, and there aren't all that many
* of them in a given command).
*
*/
public class EasTags {
// Wbxml page definitions for EAS
static final int AIRSYNC = 0x00;
static final int CONTACTS = 0x01;
static final int EMAIL = 0x02;
static final int CALENDAR = 0x04;
static final int MOVE = 0x05;
static final int FOLDER = 0x07;
static final int CONTACTS2 = 0x0C;
static final int PING = 0x0D;
static final int GAL = 0x10;
static final int BASE = 0x11;
// Shift applied to page numbers to generate tag
static final int PAGE_SHIFT = 6;
static final int PAGE_MASK = 0x3F; // 6 bits
static final int SYNC_PAGE = 0 << PAGE_SHIFT;
static final int SYNC_SYNC = SYNC_PAGE + 5;
static final int SYNC_RESPONSES = SYNC_PAGE + 6;
static final int SYNC_ADD = SYNC_PAGE + 7;
static final int SYNC_CHANGE = SYNC_PAGE + 8;
static final int SYNC_DELETE = SYNC_PAGE + 9;
static final int SYNC_FETCH = SYNC_PAGE + 0xA;
static final int SYNC_SYNC_KEY = SYNC_PAGE + 0xB;
static final int SYNC_CLIENT_ID = SYNC_PAGE + 0xC;
static final int SYNC_SERVER_ID = SYNC_PAGE + 0xD;
static final int SYNC_STATUS = SYNC_PAGE + 0xE;
static final int SYNC_COLLECTION = SYNC_PAGE + 0xF;
static final int SYNC_CLASS = SYNC_PAGE + 0x10;
static final int SYNC_VERSION = SYNC_PAGE + 0x11;
static final int SYNC_COLLECTION_ID = SYNC_PAGE + 0x12;
static final int SYNC_GET_CHANGES = SYNC_PAGE + 0x13;
static final int SYNC_MORE_AVAILABLE = SYNC_PAGE + 0x14;
static final int SYNC_WINDOW_SIZE = SYNC_PAGE + 0x15;
static final int SYNC_COMMANDS = SYNC_PAGE + 0x16;
static final int SYNC_OPTIONS = SYNC_PAGE + 0x17;
static final int SYNC_FILTER_TYPE = SYNC_PAGE + 0x18;
static final int SYNC_TRUNCATION = SYNC_PAGE + 0x19;
static final int SYNC_RTF_TRUNCATION = SYNC_PAGE + 0x1A;
static final int SYNC_CONFLICT = SYNC_PAGE + 0x1B;
static final int SYNC_COLLECTIONS = SYNC_PAGE + 0x1C;
static final int SYNC_APPLICATION_DATA = SYNC_PAGE + 0x1D;
static final int SYNC_DELETES_AS_MOVES = SYNC_PAGE + 0x1E;
static final int SYNC_NOTIFY_GUID = SYNC_PAGE + 0x1F;
static final int SYNC_SUPPORTED = SYNC_PAGE + 0x20;
static final int SYNC_SOFT_DELETE = SYNC_PAGE + 0x21;
static final int SYNC_MIME_SUPPORT = SYNC_PAGE + 0x22;
static final int SYNC_MIME_TRUNCATION = SYNC_PAGE + 0x23;
static final int SYNC_WAIT = SYNC_PAGE + 0x24;
static final int SYNC_LIMIT = SYNC_PAGE + 0x25;
static final int SYNC_PARTIAL = SYNC_PAGE + 0x26;
static final int CONTACTS_PAGE = CONTACTS << PAGE_SHIFT;
static final int CONTACTS_ANNIVERSARY = CONTACTS_PAGE + 5;
static final int CONTACTS_ASSISTANT_NAME = CONTACTS_PAGE + 6;
static final int CONTACTS_ASSISTANT_TELEPHONE_NUMBER = CONTACTS_PAGE + 7;
static final int CONTACTS_BIRTHDAY = CONTACTS_PAGE + 8;
static final int CONTACTS_BODY = CONTACTS_PAGE + 9;
static final int CONTACTS_BODY_SIZE = CONTACTS_PAGE + 0xA;
static final int CONTACTS_BODY_TRUNCATED = CONTACTS_PAGE + 0xB;
static final int CONTACTS_BUSINESS2_TELEPHONE_NUMBER = CONTACTS_PAGE + 0xC;
static final int CONTACTS_BUSINESS_ADDRESS_CITY = CONTACTS_PAGE + 0xD;
static final int CONTACTS_BUSINESS_ADDRESS_COUNTRY = CONTACTS_PAGE + 0xE;
static final int CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE = CONTACTS_PAGE + 0xF;
static final int CONTACTS_BUSINESS_ADDRESS_STATE = CONTACTS_PAGE + 0x10;
static final int CONTACTS_BUSINESS_ADDRESS_STREET = CONTACTS_PAGE + 0x11;
static final int CONTACTS_BUSINESS_FAX_NUMBER = CONTACTS_PAGE + 0x12;
static final int CONTACTS_BUSINESS_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x13;
static final int CONTACTS_CAR_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x14;
static final int CONTACTS_CATEGORIES = CONTACTS_PAGE + 0x15;
static final int CONTACTS_CATEGORY = CONTACTS_PAGE + 0x16;
static final int CONTACTS_CHILDREN = CONTACTS_PAGE + 0x17;
static final int CONTACTS_CHILD = CONTACTS_PAGE + 0x18;
static final int CONTACTS_COMPANY_NAME = CONTACTS_PAGE + 0x19;
static final int CONTACTS_DEPARTMENT = 0x1A;
static final int CONTACTS_EMAIL1_ADDRESS = CONTACTS_PAGE + 0x1B;
static final int CONTACTS_EMAIL2_ADDRESS = CONTACTS_PAGE + 0x1C;
static final int CONTACTS_EMAIL3_ADDRESS = CONTACTS_PAGE + 0x1D;
static final int CONTACTS_FILE_AS = CONTACTS_PAGE + 0x1E;
static final int CONTACTS_FIRST_NAME = CONTACTS_PAGE + 0x1F;
static final int CONTACTS_HOME2_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x20;
static final int CONTACTS_HOME_ADDRESS_CITY = CONTACTS_PAGE + 0x21;
static final int CONTACTS_HOME_ADDRESS_COUNTRY = CONTACTS_PAGE + 0x22;
static final int CONTACTS_HOME_ADDRESS_POSTAL_CODE = CONTACTS_PAGE + 0x23;
static final int CONTACTS_HOME_ADDRESS_STATE = CONTACTS_PAGE + 0x24;
static final int CONTACTS_HOME_ADDRESS_STREET = CONTACTS_PAGE + 0x25;
static final int CONTACTS_HOME_FAX_NUMBER = CONTACTS_PAGE + 0x26;
static final int CONTACTS_HOME_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x27;
static final int CONTACTS_JOB_TITLE = CONTACTS_PAGE + 0x28;
static final int CONTACTS_LAST_NAME = CONTACTS_PAGE + 0x29;
static final int CONTACTS_MIDDLE_NAME = CONTACTS_PAGE + 0x2A;
static final int CONTACTS_MOBILE_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x2B;
static final int CONTACTS_OFFICE_LOCATION = CONTACTS_PAGE + 0x2C;
static final int CONTACTS_OTHER_ADDRESS_CITY = CONTACTS_PAGE + 0x2D;
static final int CONTACTS_OTHER_ADDRESS_COUNTRY = CONTACTS_PAGE + 0x2E;
static final int CONTACTS_OTHER_ADDRESS_POSTAL_CODE = CONTACTS_PAGE + 0x2F;
static final int CONTACTS_OTHER_ADDRESS_STATE = CONTACTS_PAGE + 0x30;
static final int CONTACTS_OTHER_ADDRESS_STREET = CONTACTS_PAGE + 0x31;
static final int CONTACTS_PAGER_NUMBER = CONTACTS_PAGE + 0x32;
static final int CONTACTS_RADIO_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x33;
static final int CONTACTS_SPOUSE = CONTACTS_PAGE + 0x34;
static final int CONTACTS_SUFFIX = CONTACTS_PAGE + 0x35;
static final int CONTACTS_TITLE = CONTACTS_PAGE + 0x36;
static final int CONTACTS_WEBPAGE = CONTACTS_PAGE + 0x37;
static final int CONTACTS_YOMI_COMPANY_NAME = CONTACTS_PAGE + 0x38;
static final int CONTACTS_YOMI_FIRST_NAME = CONTACTS_PAGE + 0x39;
static final int CONTACTS_YOMI_LAST_NAME = CONTACTS_PAGE + 0x3A;
static final int CONTACTS_COMPRESSED_RTF = CONTACTS_PAGE + 0x3B;
static final int CONTACTS_PICTURE = CONTACTS_PAGE + 0x3C;
static final int CALENDAR_PAGE = CALENDAR << PAGE_SHIFT;
static final int CALENDAR_TIME_ZONE = CALENDAR_PAGE + 5;
static final int CALENDAR_ALL_DAY_EVENT = CALENDAR_PAGE + 6;
static final int CALENDAR_ATTENDEES = CALENDAR_PAGE + 7;
static final int CALENDAR_ATTENDEE = CALENDAR_PAGE + 8;
static final int CALENDAR_ATTENDEE_EMAIL = CALENDAR_PAGE + 9;
static final int CALENDAR_ATTENDEE_NAME = CALENDAR_PAGE + 0xA;
static final int CALENDAR_BODY = CALENDAR_PAGE + 0xB;
static final int CALENDAR_BODY_TRUNCATED = CALENDAR_PAGE + 0xC;
static final int CALENDAR_BUSY_STATUS = CALENDAR_PAGE + 0xD;
static final int CALENDAR_CATEGORIES = CALENDAR_PAGE + 0xE;
static final int CALENDAR_CATEGORY = CALENDAR_PAGE + 0xF;
static final int CALENDAR_COMPRESSED_RTF = CALENDAR_PAGE + 0x10;
static final int CALENDAR_DTSTAMP = CALENDAR_PAGE + 0x11;
static final int CALENDAR_END_TIME = CALENDAR_PAGE + 0x12;
static final int CALENDAR_EXCEPTION = CALENDAR_PAGE + 0x13;
static final int CALENDAR_EXCEPTIONS = CALENDAR_PAGE + 0x14;
static final int CALENDAR_EXCEPTION_IS_DELETED = CALENDAR_PAGE + 0x15;
static final int CALENDAR_EXCEPTION_START_TIME = CALENDAR_PAGE + 0x16;
static final int CALENDAR_LOCATION = CALENDAR_PAGE + 0x17;
static final int CALENDAR_MEETING_STATUS = CALENDAR_PAGE + 0x18;
static final int CALENDAR_ORGANIZER_EMAIL = CALENDAR_PAGE + 0x19;
static final int CALENDAR_ORGANIZER_NAME = CALENDAR_PAGE + 0x1A;
static final int CALENDAR_RECURRENCE = CALENDAR_PAGE + 0x1B;
static final int CALENDAR_RECURRENCE_TYPE = CALENDAR_PAGE + 0x1C;
static final int CALENDAR_RECURRENCE_UNTIL = CALENDAR_PAGE + 0x1D;
static final int CALENDAR_RECURRENCE_OCCURRENCES = CALENDAR_PAGE + 0x1E;
static final int CALENDAR_RECURRENCE_INTERVAL = CALENDAR_PAGE + 0x1F;
static final int CALENDAR_RECURRENCE_DAYOFWEEK = CALENDAR_PAGE + 0x20;
static final int CALENDAR_RECURRENCE_DAYOFMONTH = CALENDAR_PAGE + 0x21;
static final int CALENDAR_RECURRENCE_WEEKOFMONTH = CALENDAR_PAGE + 0x22;
static final int CALENDAR_RECURRENCE_MONTHOFYEAR = CALENDAR_PAGE + 0x23;
static final int CALENDAR_REMINDER_MINS_BEFORE = CALENDAR_PAGE + 0x24;
static final int CALENDAR_SENSITIVITY = CALENDAR_PAGE + 0x25;
static final int CALENDAR_SUBJECT = CALENDAR_PAGE + 0x26;
static final int CALENDAR_START_TIME = CALENDAR_PAGE + 0x27;
static final int CALENDAR_UID = CALENDAR_PAGE + 0x28;
static final int CALENDAR_ATTENDEE_STATUS = CALENDAR_PAGE + 0x29;
static final int CALENDAR_ATTENDEE_TYPE = CALENDAR_PAGE + 0x2A;
static final int FOLDER_PAGE = FOLDER << PAGE_SHIFT;
static final int FOLDER_FOLDERS = FOLDER_PAGE + 5;
static final int FOLDER_FOLDER = FOLDER_PAGE + 6;
static final int FOLDER_DISPLAY_NAME = FOLDER_PAGE + 7;
static final int FOLDER_SERVER_ID = FOLDER_PAGE + 8;
static final int FOLDER_PARENT_ID = FOLDER_PAGE + 9;
static final int FOLDER_TYPE = FOLDER_PAGE + 0xA;
static final int FOLDER_RESPONSE = FOLDER_PAGE + 0xB;
static final int FOLDER_STATUS = FOLDER_PAGE + 0xC;
static final int FOLDER_CONTENT_CLASS = FOLDER_PAGE + 0xD;
static final int FOLDER_CHANGES = FOLDER_PAGE + 0xE;
static final int FOLDER_ADD = FOLDER_PAGE + 0xF;
static final int FOLDER_DELETE = FOLDER_PAGE + 0x10;
static final int FOLDER_UPDATE = FOLDER_PAGE + 0x11;
static final int FOLDER_SYNC_KEY = FOLDER_PAGE + 0x12;
static final int FOLDER_FOLDER_CREATE = FOLDER_PAGE + 0x13;
static final int FOLDER_FOLDER_DELETE= FOLDER_PAGE + 0x14;
static final int FOLDER_FOLDER_UPDATE = FOLDER_PAGE + 0x15;
static final int FOLDER_FOLDER_SYNC = FOLDER_PAGE + 0x16;
static final int FOLDER_COUNT = FOLDER_PAGE + 0x17;
static final int FOLDER_VERSION = FOLDER_PAGE + 0x18;
static final int EMAIL_PAGE = EMAIL << PAGE_SHIFT;
static final int EMAIL_ATTACHMENT = EMAIL_PAGE + 5;
static final int EMAIL_ATTACHMENTS = EMAIL_PAGE + 6;
static final int EMAIL_ATT_NAME = EMAIL_PAGE + 7;
static final int EMAIL_ATT_SIZE = EMAIL_PAGE + 8;
static final int EMAIL_ATT0ID = EMAIL_PAGE + 9;
static final int EMAIL_ATT_METHOD = EMAIL_PAGE + 0xA;
static final int EMAIL_ATT_REMOVED = EMAIL_PAGE + 0xB;
static final int EMAIL_BODY = EMAIL_PAGE + 0xC;
static final int EMAIL_BODY_SIZE = EMAIL_PAGE + 0xD;
static final int EMAIL_BODY_TRUNCATED = EMAIL_PAGE + 0xE;
static final int EMAIL_DATE_RECEIVED = EMAIL_PAGE + 0xF;
static final int EMAIL_DISPLAY_NAME = EMAIL_PAGE + 0x10;
static final int EMAIL_DISPLAY_TO = EMAIL_PAGE + 0x11;
static final int EMAIL_IMPORTANCE = EMAIL_PAGE + 0x12;
static final int EMAIL_MESSAGE_CLASS = EMAIL_PAGE + 0x13;
static final int EMAIL_SUBJECT = EMAIL_PAGE + 0x14;
static final int EMAIL_READ = EMAIL_PAGE + 0x15;
static final int EMAIL_TO = EMAIL_PAGE + 0x16;
static final int EMAIL_CC = EMAIL_PAGE + 0x17;
static final int EMAIL_FROM = EMAIL_PAGE + 0x18;
static final int EMAIL_REPLY_TO = EMAIL_PAGE + 0x19;
static final int EMAIL_ALL_DAY_EVENT = EMAIL_PAGE + 0x1A;
static final int EMAIL_CATEGORIES = EMAIL_PAGE + 0x1B;
static final int EMAIL_CATEGORY = EMAIL_PAGE + 0x1C;
static final int EMAIL_DTSTAMP = EMAIL_PAGE + 0x1D;
static final int EMAIL_END_TIME = EMAIL_PAGE + 0x1E;
static final int EMAIL_INSTANCE_TYPE = EMAIL_PAGE + 0x1F;
static final int EMAIL_INTD_BUSY_STATUS = EMAIL_PAGE + 0x20;
static final int EMAIL_LOCATION = EMAIL_PAGE + 0x21;
static final int EMAIL_MEETING_REQUEST = EMAIL_PAGE + 0x22;
static final int EMAIL_ORGANIZER = EMAIL_PAGE + 0x23;
static final int EMAIL_RECURRENCE_ID = EMAIL_PAGE + 0x24;
static final int EMAIL_REMINDER = EMAIL_PAGE + 0x25;
static final int EMAIL_RESPONSE_REQUESTED = EMAIL_PAGE + 0x26;
static final int EMAIL_RECURRENCES = EMAIL_PAGE + 0x27;
static final int EMAIL_RECURRENCE = EMAIL_PAGE + 0x28;
static final int EMAIL_RECURRENCE_TYPE = EMAIL_PAGE + 0x29;
static final int EMAIL_RECURRENCE_UNTIL = EMAIL_PAGE + 0x2A;
static final int EMAIL_RECURRENCE_OCCURRENCES = EMAIL_PAGE + 0x2B;
static final int EMAIL_RECURRENCE_INTERVAL = EMAIL_PAGE + 0x2C;
static final int EMAIL_RECURRENCE_DAYOFWEEK = EMAIL_PAGE + 0x2D;
static final int EMAIL_RECURRENCE_DAYOFMONTH = EMAIL_PAGE + 0x2E;
static final int EMAIL_RECURRENCE_WEEKOFMONTH = EMAIL_PAGE + 0x2F;
static final int EMAIL_RECURRENCE_MONTHOFYEAR = EMAIL_PAGE + 0x30;
static final int EMAIL_START_TIME = EMAIL_PAGE + 0x31;
static final int EMAIL_SENSITIVITY = EMAIL_PAGE + 0x32;
static final int EMAIL_TIME_ZONE = EMAIL_PAGE + 0x33;
static final int EMAIL_GLOBAL_OBJID = EMAIL_PAGE + 0x34;
static final int EMAIL_THREAD_TOPIC = EMAIL_PAGE + 0x35;
static final int EMAIL_MIME_DATA = EMAIL_PAGE + 0x36;
static final int EMAIL_MIME_TRUNCATED = EMAIL_PAGE + 0x37;
static final int EMAIL_MIME_SIZE = EMAIL_PAGE + 0x38;
static final int EMAIL_INTERNET_CPID = EMAIL_PAGE + 0x39;
static final int EMAIL_FLAG = EMAIL_PAGE + 0x3A;
static final int EMAIL_FLAG_STATUS = EMAIL_PAGE + 0x3B;
static final int EMAIL_CONTENT_CLASS = EMAIL_PAGE + 0x3C;
static final int EMAIL_FLAG_TYPE = EMAIL_PAGE + 0x3D;
static final int EMAIL_COMPLETE_TIME = EMAIL_PAGE + 0x3E;
static final int MOVE_PAGE = MOVE << PAGE_SHIFT;
static final int MOVE_MOVE_ITEMS = MOVE_PAGE + 5;
static final int MOVE_MOVE = MOVE_PAGE + 6;
static final int MOVE_SRCMSGID = MOVE_PAGE + 7;
static final int MOVE_SRCFLDID = MOVE_PAGE + 8;
static final int MOVE_DSTFLDID = MOVE_PAGE + 9;
static final int MOVE_RESPONSE = MOVE_PAGE + 0xA;
static final int MOVE_STATUS = MOVE_PAGE + 0xB;
static final int MOVE_DSTMSGID = MOVE_PAGE + 0xC;
static final int CONTACTS2_PAGE = CONTACTS2 << PAGE_SHIFT;
static final int CONTACTS2_CUSTOMER_ID = CONTACTS2_PAGE + 5;
static final int CONTACTS2_GOVERNMENT_ID = CONTACTS2_PAGE + 6;
static final int CONTACTS2_IM_ADDRESS = CONTACTS2_PAGE + 7;
static final int CONTACTS2_IM_ADDRESS_2 = CONTACTS2_PAGE + 8;
static final int CONTACTS2_IM_ADDRESS_3 = CONTACTS2_PAGE + 9;
static final int CONTACTS2_MANAGER_NAME = CONTACTS2_PAGE + 0xA;
static final int CONTACTS2_COMPANY_MAIN_PHONE = CONTACTS2_PAGE + 0xB;
static final int CONTACTS2_ACCOUNT_NAME = CONTACTS2_PAGE + 0xC;
static final int CONTACTS2_NICKNAME = CONTACTS2_PAGE + 0xD;
static final int CONTACTS2_MMS = CONTACTS2_PAGE + 0xE;
// The Ping constants are used by EasSyncService, and need to be public
static final int PING_PAGE = PING << PAGE_SHIFT;
public static final int PING_PING = PING_PAGE + 5;
public static final int PING_AUTD_STATE = PING_PAGE + 6;
public static final int PING_STATUS = PING_PAGE + 7;
public static final int PING_HEARTBEAT_INTERVAL = PING_PAGE + 8;
public static final int PING_FOLDERS = PING_PAGE + 9;
public static final int PING_FOLDER = PING_PAGE + 0xA;
public static final int PING_ID = PING_PAGE + 0xB;
public static final int PING_CLASS = PING_PAGE + 0xC;
public static final int PING_MAX_FOLDERS = PING_PAGE + 0xD;
static final int BASE_PAGE = BASE << PAGE_SHIFT;
static final int BASE_BODY_PREFERENCE = BASE_PAGE + 5;
static final int BASE_TYPE = BASE_PAGE + 6;
static final int BASE_TRUNCATION_SIZE = BASE_PAGE + 7;
static final int BASE_ALL_OR_NONE = BASE_PAGE + 8;
static final int BASE_RESERVED = BASE_PAGE + 9;
static final int BASE_BODY = BASE_PAGE + 0xA;
static final int BASE_DATA = BASE_PAGE + 0xB;
static final int BASE_ESTIMATED_DATA_SIZE = BASE_PAGE + 0xC;
static final int BASE_TRUNCATED = BASE_PAGE + 0xD;
static final int BASE_ATTACHMENTS = BASE_PAGE + 0xE;
static final int BASE_ATTACHMENT = BASE_PAGE + 0xF;
static final int BASE_DISPLAY_NAME = BASE_PAGE + 0x10;
static final int BASE_FILE_REFERENCE = BASE_PAGE + 0x11;
static final int BASE_METHOD = BASE_PAGE + 0x12;
static final int BASE_CONTENT_ID = BASE_PAGE + 0x13;
static final int BASE_CONTENT_LOCATION = BASE_PAGE + 0x14;
static final int BASE_IS_INLINE = BASE_PAGE + 0x15;
static final int BASE_NATIVE_BODY_TYPE = BASE_PAGE + 0x16;
static final int BASE_CONTENT_TYPE = BASE_PAGE + 0x17;
static public String[][] pages = {
{ // 0x00 AirSync
"Sync", "Responses", "Add", "Change", "Delete", "Fetch", "SyncKey", "ClientId",
"ServerId", "Status", "Collection", "Class", "Version", "CollectionId", "GetChanges",
"MoreAvailable", "WindowSize", "Commands", "Options", "FilterType", "Truncation",
"RTFTruncation", "Conflict", "Collections", "ApplicationData", "DeletesAsMoves",
"NotifyGUID", "Supported", "SoftDelete", "MIMESupport", "MIMETruncation", "Wait",
"Limit", "Partial"
},
{
// 0x01 Contacts
"Anniversary", "AssistantName", "AssistantTelephoneNumber", "Birthday", "ContactsBody",
"ContactsBodySize", "ContactsBodyTruncated", "Business2TelephoneNumber",
"BusinessAddressCity",
"BusinessAddressCountry", "BusinessAddressPostalCode", "BusinessAddressState",
"BusinessAddressStreet", "BusinessFaxNumber", "BusinessTelephoneNumber",
"CarTelephoneNumber", "ContactsCategories", "ContactsCategory", "Children", "Child",
"CompanyName", "Department", "Email1Address", "Email2Address", "Email3Address",
"FileAs", "FirstName", "Home2TelephoneNumber", "HomeAddressCity", "HomeAddressCountry",
"HomeAddressPostalCode", "HomeAddressState", "HomeAddressStreet", "HomeFaxNumber",
"HomeTelephoneNumber", "JobTitle", "LastName", "MiddleName", "MobileTelephoneNumber",
"OfficeLocation", "OtherAddressCity", "OtherAddressCountry",
"OtherAddressPostalCode", "OtherAddressState", "OtherAddressStreet", "PagerNumber",
"RadioTelephoneNumber", "Spouse", "Suffix", "Title", "Webpage", "YomiCompanyName",
"YomiFirstName", "YomiLastName", "CompressedRTF", "Picture"
},
{
// 0x02 Email
"Attachment", "Attachments", "AttName", "AttSize", "Add0Id", "AttMethod", "AttRemoved",
"Body", "BodySize", "BodyTruncated", "DateReceived", "DisplayName", "DisplayTo",
"Importance", "MessageClass", "Subject", "Read", "To", "CC", "From", "ReplyTo",
"AllDayEvent", "Categories", "Category", "DTStamp", "EndTime", "InstanceType",
"IntDBusyStatus", "Location", "MeetingRequest", "Organizer", "RecurrenceId", "Reminder",
"ResponseRequested", "Recurrences", "Recurence", "Recurrence_Type", "Recurrence_Until",
"Recurrence_Occurrences", "Recurrence_Interval", "Recurrence_DayOfWeek",
"Recurrence_DayOfMonth", "Recurrence_WeekOfMonth", "Recurrence_MonthOfYear",
"StartTime", "Sensitivity", "TimeZone", "GlobalObjId", "ThreadTopic", "MIMEData",
"MIMETruncated", "MIMESize", "InternetCPID", "Flag", "FlagStatus", "EmailContentClass",
"FlagType", "CompleteTime"
},
{
// 0x03 AirNotify
},
{
// 0x04 Calendar
"CalTimeZone", "CalAllDayEvent", "CalAttendees", "CalAttendee", "CalAttendee_Email",
"CalAttendee_Name", "CalBody", "CalBodyTruncated", "CalBusyStatus", "CalCategories",
"CalCategory", "CalCompressed_RTF", "CalDTStamp", "CalEndTime", "CalExeption",
"CalExceptions", "CalException_IsDeleted", "CalException_StartTime", "CalLocation",
"CalMeetingStatus", "CalOrganizer_Email", "CalOrganizer_Name", "CalRecurrence",
"CalRecurrence_Type", "CalRecurrence_Until", "CalRecurrence_Occurrences",
"CalRecurrence_Interval", "CalRecurrence_DayOfWeek", "CalRecurrence_DayOfMonth",
"CalRecurrence_WeekOfMonth", "CalRecurrence_MonthOfYear", "CalReminder_MinsBefore",
"CalSensitivity", "CalSubject", "CalStartTime", "CalUID", "CalAttendee_Status",
"CalAttendee_Type"
},
{
// 0x05 Move
"MoveItems", "Move", "SrcMsgId", "SrcFldId", "DstFldId", "MoveResponse", "MoveStatus",
"DstMsgId"
},
{
// 0x06 ItemEstimate
},
{
// 0x07 FolderHierarchy
"Folders", "Folder", "FolderDisplayName", "FolderServerId", "FolderParentId", "Type",
"FolderResponse", "FolderStatus", "FolderContentClass", "Changes", "FolderAdd",
"FolderDelete", "FolderUpdate", "FolderSyncKey", "FolderFolderCreate",
"FolderFolderDelete", "FolderFolderUpdate", "FolderSync", "Count", "FolderVersion"
},
{
// 0x08 MeetingResponse
},
{
// 0x09 Tasks
},
{
// 0x0A ResolveRecipients
},
{
// 0x0B ValidateCert
},
{
// 0x0C Contacts2
"CustomerId", "GovernmentId", "IMAddress", "IMAddress2", "IMAddress3", "ManagerName",
"CompanyMainPhone", "AccountName", "NickName", "MMS"
},
{
// 0x0D Ping
"Ping", "AutdState", "PingStatus", "HeartbeatInterval", "PingFolders", "PingFolder",
"PingId", "PingClass", "MaxFolders"
},
{
// 0x0E Provision
"Provision", "Policies", "Policy", "PolicyType", "PolicyKey", "Data", "ProvisionStatus",
"RemoteWipe", "EASProvidionDoc", "DevicePasswordEnabled",
"AlphanumericDevicePasswordRequired",
"DeviceEncryptionEnabled", "-unused-", "AttachmentsEnabled", "MinDevicePasswordLength",
"MaxInactivityTimeDeviceLock", "MaxDevicePasswordFailedAttempts", "MaxAttachmentSize",
"AllowSimpleDevicePassword", "DevicePasswordExpiration", "DevicePasswordHistory",
"AllowStorageCard", "AllowCamera", "RequireDeviceEncryption",
"AllowUnsignedApplications", "AllowUnsignedInstallationPackages",
"MinDevicePasswordComplexCharacters", "AllowWiFi", "AllowTextMessaging",
"AllowPOPIMAPEmail", "AllowBluetooth", "AllowIrDA", "RequireManualSyncWhenRoaming",
"AllowDesktopSync",
"MaxCalendarAgeFilder", "AllowHTMLEmail", "MaxEmailAgeFilder",
"MaxEmailBodyTruncationSize", "MaxEmailHTMLBodyTruncationSize",
"RequireSignedSMIMEMessages", "RequireEncryptedSMIMEMessages",
"RequireSignedSMIMEAlgorithm", "RequireEncryptionSMIMEAlgorithm",
"AllowSMIMEEncryptionAlgorithmNegotiation", "AllowSMIMESoftCerts", "AllowBrowser",
"AllowConsumerEmail", "AllowRemoteDesktop", "AllowInternetSharing",
"UnapprovedInROMApplicationList", "ApplicationName", "ApprovedApplicationList", "Hash"
},
{
// 0x0F Search
},
{
// 0x10 Gal
"GalDisplayName", "GalPhone", "GalOffice", "GalTitle", "GalCompany", "GalAlias",
"GalFirstName", "GalLastName", "GalHomePhone", "GalMobilePhone", "GalEmailAddress"
},
{
// 0x11 AirSyncBase
"BodyPreference", "BodyPreferenceType", "BodyPreferenceTruncationSize", "AllOrNone",
"--unused--", "BaseBody", "BaseData", "BaseEstimatedDataSize", "BaseTruncated",
"BaseAttachments", "BaseAttachment", "BaseDisplayName", "FileReference", "BaseMethod",
"BaseContentId", "BaseContentLocation", "BaseIsInline", "BaseNativeBodyType",
"BaseContentType"
},
{
// 0x12 Settings
},
{
// 0x13 DocumentLibrary
},
{
// 0x14 ItemOperations
}
};
}

View File

@ -48,9 +48,7 @@ import java.util.TimeZone;
* Sync adapter for EAS email
*
*/
public class EasEmailSyncAdapter extends EasSyncAdapter {
private static boolean DEBUG_LOGGING = false; // DON'T CHECK THIS IN SET TO TRUE
public class EmailSyncAdapter extends AbstractSyncAdapter {
private static final int UPDATES_READ_COLUMN = 0;
private static final int UPDATES_MAILBOX_KEY_COLUMN = 1;
@ -63,7 +61,7 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();
public EasEmailSyncAdapter(Mailbox mailbox, EasSyncService service) {
public EmailSyncAdapter(Mailbox mailbox, EasSyncService service) {
super(mailbox, service);
}
@ -73,7 +71,7 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
return p.parse();
}
public class EasEmailSyncParser extends EasContentParser {
public class EasEmailSyncParser extends ContentParser {
private static final String WHERE_SERVER_ID_AND_MAILBOX_KEY =
SyncColumns.SERVER_ID + "=? and " + MessageColumns.MAILBOX_KEY + "=?";
@ -83,9 +81,6 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
public EasEmailSyncParser(InputStream in, EasSyncService service) throws IOException {
super(in, service);
mMailboxIdAsString = Long.toString(mMailbox.mId);
if (DEBUG_LOGGING) {
setDebug(true);
}
}
@Override
@ -101,15 +96,15 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
public void addData (Message msg) throws IOException {
ArrayList<Attachment> atts = new ArrayList<Attachment>();
while (nextTag(EasTags.SYNC_APPLICATION_DATA) != END) {
while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
switch (tag) {
case EasTags.EMAIL_ATTACHMENTS:
case Tags.EMAIL_ATTACHMENTS:
attachmentsParser(atts, msg);
break;
case EasTags.EMAIL_TO:
case Tags.EMAIL_TO:
msg.mTo = Address.pack(Address.parse(getValue()));
break;
case EasTags.EMAIL_FROM:
case Tags.EMAIL_FROM:
String from = getValue();
String sender = from;
int q = from.indexOf('\"');
@ -122,13 +117,13 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
msg.mDisplayName = sender;
msg.mFrom = Address.pack(Address.parse(from));
break;
case EasTags.EMAIL_CC:
case Tags.EMAIL_CC:
msg.mCc = Address.pack(Address.parse(getValue()));
break;
case EasTags.EMAIL_REPLY_TO:
case Tags.EMAIL_REPLY_TO:
msg.mReplyTo = Address.pack(Address.parse(getValue()));
break;
case EasTags.EMAIL_DATE_RECEIVED:
case Tags.EMAIL_DATE_RECEIVED:
String date = getValue();
// 2009-02-11T18:03:03.627Z
GregorianCalendar cal = new GregorianCalendar();
@ -140,19 +135,19 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
msg.mTimeStamp = cal.getTimeInMillis();
break;
case EasTags.EMAIL_SUBJECT:
case Tags.EMAIL_SUBJECT:
msg.mSubject = getValue();
break;
case EasTags.EMAIL_READ:
case Tags.EMAIL_READ:
msg.mFlagRead = getValueInt() == 1;
break;
case EasTags.BASE_BODY:
case Tags.BASE_BODY:
bodyParser(msg);
break;
case EasTags.EMAIL_FLAG:
case Tags.EMAIL_FLAG:
msg.mFlagFavorite = flagParser();
break;
case EasTags.EMAIL_BODY:
case Tags.EMAIL_BODY:
String text = getValue();
msg.mText = text;
msg.mTextInfo = "X;X;8;" + text.length(); // location;encoding;charset;size
@ -173,12 +168,12 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
msg.mMailboxKey = mMailbox.mId;
msg.mFlagLoaded = Message.LOADED;
while (nextTag(EasTags.SYNC_ADD) != END) {
while (nextTag(Tags.SYNC_ADD) != END) {
switch (tag) {
case EasTags.SYNC_SERVER_ID:
case Tags.SYNC_SERVER_ID:
msg.mServerId = getValue();
break;
case EasTags.SYNC_APPLICATION_DATA:
case Tags.SYNC_APPLICATION_DATA:
addData(msg);
break;
default:
@ -194,9 +189,9 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
// For now, we only care about the "active" state
private Boolean flagParser() throws IOException {
Boolean state = false;
while (nextTag(EasTags.EMAIL_FLAG) != END) {
while (nextTag(Tags.EMAIL_FLAG) != END) {
switch (tag) {
case EasTags.EMAIL_FLAG_STATUS:
case Tags.EMAIL_FLAG_STATUS:
state = true;
break;
default:
@ -209,12 +204,12 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
private void bodyParser(Message msg) throws IOException {
String bodyType = Eas.BODY_PREFERENCE_TEXT;
String body = "";
while (nextTag(EasTags.EMAIL_BODY) != END) {
while (nextTag(Tags.EMAIL_BODY) != END) {
switch (tag) {
case EasTags.BASE_TYPE:
case Tags.BASE_TYPE:
bodyType = getValue();
break;
case EasTags.BASE_DATA:
case Tags.BASE_DATA:
body = getValue();
break;
default:
@ -237,15 +232,15 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
String length = null;
String location = null;
while (nextTag(EasTags.EMAIL_ATTACHMENT) != END) {
while (nextTag(Tags.EMAIL_ATTACHMENT) != END) {
switch (tag) {
case EasTags.EMAIL_DISPLAY_NAME:
case Tags.EMAIL_DISPLAY_NAME:
fileName = getValue();
break;
case EasTags.EMAIL_ATT_NAME:
case Tags.EMAIL_ATT_NAME:
location = getValue();
break;
case EasTags.EMAIL_ATT_SIZE:
case Tags.EMAIL_ATT_SIZE:
length = getValue();
break;
default:
@ -294,9 +289,9 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
}
private void attachmentsParser(ArrayList<Attachment> atts, Message msg) throws IOException {
while (nextTag(EasTags.EMAIL_ATTACHMENTS) != END) {
while (nextTag(Tags.EMAIL_ATTACHMENTS) != END) {
switch (tag) {
case EasTags.EMAIL_ATTACHMENT:
case Tags.EMAIL_ATTACHMENT:
attachmentParser(atts, msg);
break;
default:
@ -313,9 +308,9 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
}
private void deleteParser(ArrayList<Long> deletes) throws IOException {
while (nextTag(EasTags.SYNC_DELETE) != END) {
while (nextTag(Tags.SYNC_DELETE) != END) {
switch (tag) {
case EasTags.SYNC_SERVER_ID:
case Tags.SYNC_SERVER_ID:
String serverId = getValue();
// Find the message in this mailbox with the given serverId
Cursor c = getServerIdCursor(serverId, Message.ID_COLUMN_PROJECTION);
@ -353,9 +348,9 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
Boolean oldFlag = false;
Boolean flag = null;
long id = 0;
while (nextTag(EasTags.SYNC_CHANGE) != END) {
while (nextTag(Tags.SYNC_CHANGE) != END) {
switch (tag) {
case EasTags.SYNC_SERVER_ID:
case Tags.SYNC_SERVER_ID:
serverId = getValue();
Cursor c = getServerIdCursor(serverId, Message.LIST_PROJECTION);
try {
@ -369,13 +364,13 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
c.close();
}
break;
case EasTags.EMAIL_READ:
case Tags.EMAIL_READ:
read = getValueInt() == 1;
break;
case EasTags.EMAIL_FLAG:
case Tags.EMAIL_FLAG:
flag = flagParser();
break;
case EasTags.SYNC_APPLICATION_DATA:
case Tags.SYNC_APPLICATION_DATA:
break;
default:
skipTag();
@ -396,12 +391,12 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
ArrayList<Long> deletedEmails = new ArrayList<Long>();
ArrayList<ServerChange> changedEmails = new ArrayList<ServerChange>();
while (nextTag(EasTags.SYNC_COMMANDS) != END) {
if (tag == EasTags.SYNC_ADD) {
while (nextTag(Tags.SYNC_COMMANDS) != END) {
if (tag == Tags.SYNC_ADD) {
addParser(newEmails);
} else if (tag == EasTags.SYNC_DELETE) {
} else if (tag == Tags.SYNC_DELETE) {
deleteParser(deletedEmails);
} else if (tag == EasTags.SYNC_CHANGE) {
} else if (tag == Tags.SYNC_CHANGE) {
changeParser(changedEmails);
} else
skipTag();
@ -488,7 +483,7 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
}
@Override
public boolean sendLocalChanges(EasSerializer s, EasSyncService service) throws IOException {
public boolean sendLocalChanges(Serializer s, EasSyncService service) throws IOException {
Context context = service.mContext;
ContentResolver cr = context.getContentResolver();
@ -502,13 +497,13 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
try {
while (c.moveToNext()) {
if (first) {
s.start("Commands");
s.start(Tags.SYNC_COMMANDS);
first = false;
}
// Send the command to delete this message
s.start("Delete")
.data("ServerId", c.getString(Message.LIST_SERVER_ID_COLUMN))
.end("Delete");
s.start(Tags.SYNC_DELETE)
.data(Tags.SYNC_SERVER_ID, c.getString(Message.LIST_SERVER_ID_COLUMN))
.end(); // SYNC_DELETE
mDeletedIdList.add(c.getLong(Message.LIST_ID_COLUMN));
}
} finally {
@ -543,13 +538,13 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
// If the message is now in the trash folder, it has been deleted by the user
if (currentCursor.getLong(UPDATES_MAILBOX_KEY_COLUMN) == trashMailboxId) {
if (first) {
s.start("Commands");
s.start(Tags.SYNC_COMMANDS);
first = false;
}
// Send the command to delete this message
s.start("Delete")
.data("ServerId", currentCursor.getString(UPDATES_SERVER_ID_COLUMN))
.end("Delete");
s.start(Tags.SYNC_DELETE)
.data(Tags.SYNC_SERVER_ID, currentCursor.getString(UPDATES_SERVER_ID_COLUMN))
.end(); // SYNC_DELETE
continue;
}
@ -559,18 +554,17 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
continue;
}
if (first) {
s.start("Commands");
s.start(Tags.SYNC_COMMANDS);
first = false;
}
// Send the change to "read". We'll do "flagged" here eventually as well
// TODO Add support for flags here (EAS 12.0 and above)
// Or is this not safe??
s.start("Change")
.data("ServerId", c.getString(Message.LIST_SERVER_ID_COLUMN))
.start("ApplicationData")
.data("Read", Integer.toString(read))
.end("ApplicationData")
.end("Change");
s.start(Tags.SYNC_CHANGE)
.data(Tags.SYNC_SERVER_ID, c.getString(Message.LIST_SERVER_ID_COLUMN))
.start(Tags.SYNC_APPLICATION_DATA)
.data(Tags.EMAIL_READ, Integer.toString(read))
.end().end(); // SYNC_APPLICATION_DATA, SYNC_CHANGE
} finally {
currentCursor.close();
}
@ -580,7 +574,7 @@ public class EasEmailSyncAdapter extends EasSyncAdapter {
}
if (!first) {
s.end("Commands");
s.end(); // SYNC_COMMANDS
}
return false;
}

View File

@ -49,9 +49,7 @@ import java.util.List;
* Handles the addition, deletion, and changes to folders in the user's Exchange account.
**/
public class EasFolderSyncParser extends EasParser {
private static boolean DEBUG_LOGGING = true;
public class FolderSyncParser extends Parser {
public static final String TAG = "FolderSyncParser";
@ -85,22 +83,15 @@ public class EasFolderSyncParser extends EasParser {
new String[] {MailboxColumns.ID, MailboxColumns.SERVER_ID};
private Account mAccount;
private long mAccountId;
private String mAccountIdAsString;
private EasSyncService mService;
private Context mContext;
private ContentResolver mContentResolver;
private MockParserStream mMock = null;
private String[] mBindArguments = new String[2];
public EasFolderSyncParser(InputStream in, EasSyncService service) throws IOException {
public FolderSyncParser(InputStream in, EasSyncService service) throws IOException {
super(in);
mService = service;
mAccount = service.mAccount;
@ -111,18 +102,16 @@ public class EasFolderSyncParser extends EasParser {
if (in instanceof MockParserStream) {
mMock = (MockParserStream)in;
}
if (DEBUG_LOGGING) {
setDebug(true);
}
}
@Override
public boolean parse() throws IOException {
int status;
boolean res = false;
if (nextTag(START_DOCUMENT) != EasTags.FOLDER_FOLDER_SYNC)
if (nextTag(START_DOCUMENT) != Tags.FOLDER_FOLDER_SYNC)
throw new IOException();
while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
if (tag == EasTags.FOLDER_STATUS) {
if (tag == Tags.FOLDER_STATUS) {
status = getValueInt();
if (status != Eas.FOLDER_STATUS_OK) {
mService.errorLog("FolderSync failed: " + status);
@ -141,10 +130,10 @@ public class EasFolderSyncParser extends EasParser {
throw new IOException();
}
}
} else if (tag == EasTags.FOLDER_SYNC_KEY) {
} else if (tag == Tags.FOLDER_SYNC_KEY) {
mAccount.mSyncKey = getValue();
mService.userLog("New Account SyncKey: " + mAccount.mSyncKey);
} else if (tag == EasTags.FOLDER_CHANGES) {
} else if (tag == Tags.FOLDER_CHANGES) {
changesParser();
} else
skipTag();
@ -163,9 +152,9 @@ public class EasFolderSyncParser extends EasParser {
}
public void deleteParser(ArrayList<ContentProviderOperation> ops) throws IOException {
while (nextTag(EasTags.SYNC_DELETE) != END) {
while (nextTag(Tags.SYNC_DELETE) != END) {
switch (tag) {
case EasTags.FOLDER_SERVER_ID:
case Tags.FOLDER_SERVER_ID:
String serverId = getValue();
// Find the mailbox in this account with the given serverId
Cursor c = getServerIdCursor(serverId);
@ -192,21 +181,21 @@ public class EasFolderSyncParser extends EasParser {
String parentId = null;
int type = 0;
while (nextTag(EasTags.FOLDER_ADD) != END) {
while (nextTag(Tags.FOLDER_ADD) != END) {
switch (tag) {
case EasTags.FOLDER_DISPLAY_NAME: {
case Tags.FOLDER_DISPLAY_NAME: {
name = getValue();
break;
}
case EasTags.FOLDER_TYPE: {
case Tags.FOLDER_TYPE: {
type = getValueInt();
break;
}
case EasTags.FOLDER_PARENT_ID: {
case Tags.FOLDER_PARENT_ID: {
parentId = getValue();
break;
}
case EasTags.FOLDER_SERVER_ID: {
case Tags.FOLDER_SERVER_ID: {
serverId = getValue();
break;
}
@ -241,7 +230,7 @@ public class EasFolderSyncParser extends EasParser {
case DELETED_TYPE:
m.mType = Mailbox.TYPE_TRASH;
break;
case CALENDAR_TYPE:
case CALENDAR_TYPE:
m.mType = Mailbox.TYPE_CALENDAR;
// TODO This could be push, depending on settings
// For now, no sync, since it's not yet implemented
@ -272,13 +261,13 @@ public class EasFolderSyncParser extends EasParser {
// Keep track of new boxes, deleted boxes, updated boxes
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
while (nextTag(EasTags.FOLDER_CHANGES) != END) {
while (nextTag(Tags.FOLDER_CHANGES) != END) {
// TODO Handle FOLDER_CHANGE and FOLDER_DELETE
if (tag == EasTags.FOLDER_ADD) {
if (tag == Tags.FOLDER_ADD) {
addParser(ops);
} else if (tag == EasTags.FOLDER_DELETE) {
} else if (tag == Tags.FOLDER_DELETE) {
deleteParser(ops);
} else if (tag == EasTags.FOLDER_COUNT) {
} else if (tag == Tags.FOLDER_COUNT) {
getValueInt();
} else
skipTag();

View File

@ -30,33 +30,33 @@ import java.io.InputStream;
*
* This is currently unused, as "move to folder" is not implemented in the application.
**/
public class EasMoveParser extends EasParser {
public class MoveParser extends Parser {
private static final String TAG = "EasMoveParser";
private EasSyncService mService;
private Mailbox mMailbox;
protected boolean mMoreAvailable = false;
public EasMoveParser(InputStream in, EasSyncService service) throws IOException {
public MoveParser(InputStream in, EasSyncService service) throws IOException {
super(in);
mService = service;
mMailbox = service.mMailbox;
//setDebug(true);
}
@Override
public boolean parse() throws IOException {
int status;
if (nextTag(START_DOCUMENT) != EasTags.MOVE_MOVE_ITEMS) {
if (nextTag(START_DOCUMENT) != Tags.MOVE_MOVE_ITEMS) {
throw new IOException();
}
while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
if (tag == EasTags.MOVE_RESPONSE) {
if (tag == Tags.MOVE_RESPONSE) {
// Ignore
} else if (tag == EasTags.MOVE_STATUS) {
} else if (tag == Tags.MOVE_STATUS) {
status = getValueInt();
if (status != 3) {
Log.e(TAG, "Sync failed (3 is success): " + status);
}
} else if (tag == EasTags.SYNC_RESPONSES) {
} else if (tag == Tags.SYNC_RESPONSES) {
// TODO See if any of these cases need to be handled
skipTag();
} else {

View File

@ -17,20 +17,24 @@
package com.android.exchange.adapter;
import java.io.*;
import java.util.ArrayList;
import com.android.exchange.Eas;
import com.android.exchange.EasException;
import android.content.Context;
import android.util.Log;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
/**
* Extremely fast and lightweight WBXML parser, implementing only the subset of WBXML that
* EAS uses (as defined in the EAS specification)
*
*/
public abstract class EasParser {
public abstract class Parser {
private static final String TAG = "EasParser";
@ -44,7 +48,7 @@ public abstract class EasParser {
private static final int NOT_FETCHED = Integer.MIN_VALUE;
private static final int NOT_ENDED = Integer.MIN_VALUE;
private static final int EOF_BYTE = -1;
private boolean debug = false;
private boolean logging = false;
private boolean capture = false;
private ArrayList<Integer> captureArray;
@ -119,7 +123,7 @@ public abstract class EasParser {
*
*/
{
String[][] pages = EasTags.pages;
String[][] pages = Tags.pages;
for (int i = 0; i < pages.length; i++) {
String[] page = pages[i];
if (page.length > 0) {
@ -128,8 +132,9 @@ public abstract class EasParser {
}
}
public EasParser(InputStream in) throws IOException {
public Parser(InputStream in) throws IOException {
setInput(in);
logging = Eas.PARSER_LOG;
}
/**
@ -139,7 +144,7 @@ public abstract class EasParser {
* @param val the desired state for debug output
*/
public void setDebug(boolean val) {
debug = val;
logging = val;
}
/**
@ -221,7 +226,7 @@ public abstract class EasParser {
*/
public int nextTag(int endingTag) throws IOException {
// Lose the page information
endTag = endingTag &= EasTags.PAGE_MASK;
endTag = endingTag &= Tags.PAGE_MASK;
while (getNext(false) != DONE) {
// If we're a start, set tag to include the page and return it
if (type == START) {
@ -320,7 +325,7 @@ public abstract class EasParser {
// Get the new page number
int pg = readByte();
// Save the shifted page to add into the startTag in nextTag
page = pg << EasTags.PAGE_SHIFT;
page = pg << Tags.PAGE_SHIFT;
// Retrieve the current tag table
tagTable = tagTables[pg];
id = nextId();
@ -336,7 +341,7 @@ public abstract class EasParser {
case Wbxml.END:
// End of tag
type = END;
if (debug) {
if (logging) {
name = nameArray[depth];
Log.v(TAG, "</" + name + '>');
}
@ -352,7 +357,7 @@ public abstract class EasParser {
} else {
text = readInlineString();
}
if (debug) {
if (logging) {
Log.v(TAG, asInt ? Integer.toString(num) : text);
}
break;
@ -365,7 +370,7 @@ public abstract class EasParser {
// If the high bit is set, there is content (a value) to be read
noContent = (id & 0x40) == 0;
depth++;
if (debug) {
if (logging) {
name = tagTable[startTag - 5];
Log.v(TAG, '<' + name + '>');
nameArray[depth] = name;

View File

@ -16,13 +16,13 @@
package com.android.exchange.adapter;
import com.android.exchange.EasSyncService;
import com.android.exchange.StaleFolderListException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import com.android.exchange.EasSyncService;
import com.android.exchange.StaleFolderListException;
/**
* Parse the result of a Ping command.
*
@ -30,24 +30,22 @@ import com.android.exchange.StaleFolderListException;
* If the folder list needs to be reloaded, throw a StaleFolderListException, which will be caught
* by the sync server, which will sync the updated folder list.
*/
public class EasPingParser extends EasParser {
public class PingParser extends Parser {
ArrayList<String> syncList = new ArrayList<String>();
EasSyncService mService;
public ArrayList<String> getSyncList() {
return syncList;
}
public EasPingParser(InputStream in, EasSyncService _service) throws IOException {
public PingParser(InputStream in, EasSyncService _service) throws IOException {
super(in);
mService = _service;
//setDebug(true);
}
public void parsePingFolders(ArrayList<String> syncList) throws IOException {
while (nextTag(EasTags.PING_FOLDERS) != END) {
if (tag == EasTags.PING_FOLDER) {
while (nextTag(Tags.PING_FOLDERS) != END) {
if (tag == Tags.PING_FOLDER) {
// Here we'll keep track of which mailboxes need syncing
syncList.add(getValue());
} else {
@ -59,11 +57,11 @@ public class EasPingParser extends EasParser {
@Override
public boolean parse() throws IOException, StaleFolderListException {
boolean res = false;
if (nextTag(START_DOCUMENT) != EasTags.PING_PING) {
if (nextTag(START_DOCUMENT) != Tags.PING_PING) {
throw new IOException();
}
while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
if (tag == EasTags.PING_STATUS) {
if (tag == Tags.PING_STATUS) {
int status = getValueInt();
mService.userLog("Ping completed, status = " + status);
if (status == 2) {
@ -74,7 +72,7 @@ public class EasPingParser extends EasParser {
// Status of 7 or 4 indicate a stale folder list
throw new StaleFolderListException();
}
} else if (tag == EasTags.PING_FOLDERS) {
} else if (tag == Tags.PING_FOLDERS) {
parsePingFolders(syncList);
} else {
skipTag();

View File

@ -0,0 +1,150 @@
/* Copyright (c) 2002,2003, Stefan Haustein, Oberhausen, Rhld., Germany
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE. */
//Contributors: Jonathan Cox, Bogdan Onoiu, Jerry Tian
//Simplified for Google, Inc. by Marc Blank
package com.android.exchange.adapter;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;
public class Serializer {
private static final int NOT_PENDING = -1;
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream buf = new ByteArrayOutputStream();
String pending;
int pendingTag = NOT_PENDING;
int depth;
String name;
Hashtable<String, Object> tagTable = new Hashtable<String, Object>();
private int tagPage;
public Serializer() {
super();
try {
startDocument();
} catch (IOException e) {
// Nothing to be done
}
}
public void done() throws IOException {
if (depth != 0) {
throw new IOException();
}
writeInteger(out, 0);
out.write(buf.toByteArray());
out.flush();
}
public void startDocument() throws IOException{
out.write(0x03); // version 1.3
out.write(0x01); // unknown or missing public identifier
out.write(106);
}
public void checkPendingTag(boolean degenerated) throws IOException {
if (pendingTag == NOT_PENDING)
return;
int page = pendingTag >> Tags.PAGE_SHIFT;
int tag = pendingTag & Tags.PAGE_MASK;
if (page != tagPage) {
tagPage = page;
buf.write(Wbxml.SWITCH_PAGE);
buf.write(page);
}
buf.write(degenerated ? tag : tag | 64);
pendingTag = NOT_PENDING;
}
public Serializer start(int tag) throws IOException {
checkPendingTag(false);
pendingTag = tag;
depth++;
return this;
}
public Serializer end() throws IOException {
if (pendingTag >= 0) {
checkPendingTag(true);
} else {
buf.write(Wbxml.END);
}
depth--;
return this;
}
public Serializer tag(int t) throws IOException {
start(t);
end();
return this;
}
public Serializer data(int tag, String value) throws IOException {
start(tag);
text(value);
end();
return this;
}
@Override
public String toString() {
return out.toString();
}
public Serializer text(String text) throws IOException {
checkPendingTag(false);
buf.write(Wbxml.STR_I);
writeLiteralString(buf, text);
return this;
}
static void writeInteger(OutputStream out, int i) throws IOException {
byte[] buf = new byte[5];
int idx = 0;
do {
buf[idx++] = (byte) (i & 0x7f);
i = i >> 7;
} while (i != 0);
while (idx > 1) {
out.write(buf[--idx] | 0x80);
}
out.write(buf[0]);
}
void writeLiteralString(OutputStream out, String s) throws IOException {
byte[] data = s.getBytes("UTF-8");
out.write(data);
out.write(0);
}
}

View File

@ -0,0 +1,461 @@
/*
* Copyright (C) 2008-2009 Marc Blank
* Licensed to The Android Open Source Project.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.exchange.adapter;
/**
* The wbxml tags for EAS are all defined here.
*
* The static final int's, of the form <page>_<tag> = <constant> are used in parsing incoming
* responses from the server (i.e. EasParser and its subclasses).
*
* The array of String arrays is used to construct server requests with EasSerializer. One thing
* we might do eventually is to "precompile" these requests, in part, although they should be
* fairly fast to begin with (each tag requires one HashMap lookup, and there aren't all that many
* of them in a given command).
*
*/
public class Tags {
// Wbxml page definitions for EAS
public static final int AIRSYNC = 0x00;
public static final int CONTACTS = 0x01;
public static final int EMAIL = 0x02;
public static final int CALENDAR = 0x04;
public static final int MOVE = 0x05;
public static final int FOLDER = 0x07;
public static final int CONTACTS2 = 0x0C;
public static final int PING = 0x0D;
public static final int GAL = 0x10;
public static final int BASE = 0x11;
// Shift applied to page numbers to generate tag
public static final int PAGE_SHIFT = 6;
public static final int PAGE_MASK = 0x3F; // 6 bits
public static final int SYNC_PAGE = 0 << PAGE_SHIFT;
public static final int SYNC_SYNC = SYNC_PAGE + 5;
public static final int SYNC_RESPONSES = SYNC_PAGE + 6;
public static final int SYNC_ADD = SYNC_PAGE + 7;
public static final int SYNC_CHANGE = SYNC_PAGE + 8;
public static final int SYNC_DELETE = SYNC_PAGE + 9;
public static final int SYNC_FETCH = SYNC_PAGE + 0xA;
public static final int SYNC_SYNC_KEY = SYNC_PAGE + 0xB;
public static final int SYNC_CLIENT_ID = SYNC_PAGE + 0xC;
public static final int SYNC_SERVER_ID = SYNC_PAGE + 0xD;
public static final int SYNC_STATUS = SYNC_PAGE + 0xE;
public static final int SYNC_COLLECTION = SYNC_PAGE + 0xF;
public static final int SYNC_CLASS = SYNC_PAGE + 0x10;
public static final int SYNC_VERSION = SYNC_PAGE + 0x11;
public static final int SYNC_COLLECTION_ID = SYNC_PAGE + 0x12;
public static final int SYNC_GET_CHANGES = SYNC_PAGE + 0x13;
public static final int SYNC_MORE_AVAILABLE = SYNC_PAGE + 0x14;
public static final int SYNC_WINDOW_SIZE = SYNC_PAGE + 0x15;
public static final int SYNC_COMMANDS = SYNC_PAGE + 0x16;
public static final int SYNC_OPTIONS = SYNC_PAGE + 0x17;
public static final int SYNC_FILTER_TYPE = SYNC_PAGE + 0x18;
public static final int SYNC_TRUNCATION = SYNC_PAGE + 0x19;
public static final int SYNC_RTF_TRUNCATION = SYNC_PAGE + 0x1A;
public static final int SYNC_CONFLICT = SYNC_PAGE + 0x1B;
public static final int SYNC_COLLECTIONS = SYNC_PAGE + 0x1C;
public static final int SYNC_APPLICATION_DATA = SYNC_PAGE + 0x1D;
public static final int SYNC_DELETES_AS_MOVES = SYNC_PAGE + 0x1E;
public static final int SYNC_NOTIFY_GUID = SYNC_PAGE + 0x1F;
public static final int SYNC_SUPPORTED = SYNC_PAGE + 0x20;
public static final int SYNC_SOFT_DELETE = SYNC_PAGE + 0x21;
public static final int SYNC_MIME_SUPPORT = SYNC_PAGE + 0x22;
public static final int SYNC_MIME_TRUNCATION = SYNC_PAGE + 0x23;
public static final int SYNC_WAIT = SYNC_PAGE + 0x24;
public static final int SYNC_LIMIT = SYNC_PAGE + 0x25;
public static final int SYNC_PARTIAL = SYNC_PAGE + 0x26;
public static final int CONTACTS_PAGE = CONTACTS << PAGE_SHIFT;
public static final int CONTACTS_ANNIVERSARY = CONTACTS_PAGE + 5;
public static final int CONTACTS_ASSISTANT_NAME = CONTACTS_PAGE + 6;
public static final int CONTACTS_ASSISTANT_TELEPHONE_NUMBER = CONTACTS_PAGE + 7;
public static final int CONTACTS_BIRTHDAY = CONTACTS_PAGE + 8;
public static final int CONTACTS_BODY = CONTACTS_PAGE + 9;
public static final int CONTACTS_BODY_SIZE = CONTACTS_PAGE + 0xA;
public static final int CONTACTS_BODY_TRUNCATED = CONTACTS_PAGE + 0xB;
public static final int CONTACTS_BUSINESS2_TELEPHONE_NUMBER = CONTACTS_PAGE + 0xC;
public static final int CONTACTS_BUSINESS_ADDRESS_CITY = CONTACTS_PAGE + 0xD;
public static final int CONTACTS_BUSINESS_ADDRESS_COUNTRY = CONTACTS_PAGE + 0xE;
public static final int CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE = CONTACTS_PAGE + 0xF;
public static final int CONTACTS_BUSINESS_ADDRESS_STATE = CONTACTS_PAGE + 0x10;
public static final int CONTACTS_BUSINESS_ADDRESS_STREET = CONTACTS_PAGE + 0x11;
public static final int CONTACTS_BUSINESS_FAX_NUMBER = CONTACTS_PAGE + 0x12;
public static final int CONTACTS_BUSINESS_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x13;
public static final int CONTACTS_CAR_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x14;
public static final int CONTACTS_CATEGORIES = CONTACTS_PAGE + 0x15;
public static final int CONTACTS_CATEGORY = CONTACTS_PAGE + 0x16;
public static final int CONTACTS_CHILDREN = CONTACTS_PAGE + 0x17;
public static final int CONTACTS_CHILD = CONTACTS_PAGE + 0x18;
public static final int CONTACTS_COMPANY_NAME = CONTACTS_PAGE + 0x19;
public static final int CONTACTS_DEPARTMENT = 0x1A;
public static final int CONTACTS_EMAIL1_ADDRESS = CONTACTS_PAGE + 0x1B;
public static final int CONTACTS_EMAIL2_ADDRESS = CONTACTS_PAGE + 0x1C;
public static final int CONTACTS_EMAIL3_ADDRESS = CONTACTS_PAGE + 0x1D;
public static final int CONTACTS_FILE_AS = CONTACTS_PAGE + 0x1E;
public static final int CONTACTS_FIRST_NAME = CONTACTS_PAGE + 0x1F;
public static final int CONTACTS_HOME2_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x20;
public static final int CONTACTS_HOME_ADDRESS_CITY = CONTACTS_PAGE + 0x21;
public static final int CONTACTS_HOME_ADDRESS_COUNTRY = CONTACTS_PAGE + 0x22;
public static final int CONTACTS_HOME_ADDRESS_POSTAL_CODE = CONTACTS_PAGE + 0x23;
public static final int CONTACTS_HOME_ADDRESS_STATE = CONTACTS_PAGE + 0x24;
public static final int CONTACTS_HOME_ADDRESS_STREET = CONTACTS_PAGE + 0x25;
public static final int CONTACTS_HOME_FAX_NUMBER = CONTACTS_PAGE + 0x26;
public static final int CONTACTS_HOME_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x27;
public static final int CONTACTS_JOB_TITLE = CONTACTS_PAGE + 0x28;
public static final int CONTACTS_LAST_NAME = CONTACTS_PAGE + 0x29;
public static final int CONTACTS_MIDDLE_NAME = CONTACTS_PAGE + 0x2A;
public static final int CONTACTS_MOBILE_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x2B;
public static final int CONTACTS_OFFICE_LOCATION = CONTACTS_PAGE + 0x2C;
public static final int CONTACTS_OTHER_ADDRESS_CITY = CONTACTS_PAGE + 0x2D;
public static final int CONTACTS_OTHER_ADDRESS_COUNTRY = CONTACTS_PAGE + 0x2E;
public static final int CONTACTS_OTHER_ADDRESS_POSTAL_CODE = CONTACTS_PAGE + 0x2F;
public static final int CONTACTS_OTHER_ADDRESS_STATE = CONTACTS_PAGE + 0x30;
public static final int CONTACTS_OTHER_ADDRESS_STREET = CONTACTS_PAGE + 0x31;
public static final int CONTACTS_PAGER_NUMBER = CONTACTS_PAGE + 0x32;
public static final int CONTACTS_RADIO_TELEPHONE_NUMBER = CONTACTS_PAGE + 0x33;
public static final int CONTACTS_SPOUSE = CONTACTS_PAGE + 0x34;
public static final int CONTACTS_SUFFIX = CONTACTS_PAGE + 0x35;
public static final int CONTACTS_TITLE = CONTACTS_PAGE + 0x36;
public static final int CONTACTS_WEBPAGE = CONTACTS_PAGE + 0x37;
public static final int CONTACTS_YOMI_COMPANY_NAME = CONTACTS_PAGE + 0x38;
public static final int CONTACTS_YOMI_FIRST_NAME = CONTACTS_PAGE + 0x39;
public static final int CONTACTS_YOMI_LAST_NAME = CONTACTS_PAGE + 0x3A;
public static final int CONTACTS_COMPRESSED_RTF = CONTACTS_PAGE + 0x3B;
public static final int CONTACTS_PICTURE = CONTACTS_PAGE + 0x3C;
public static final int CALENDAR_PAGE = CALENDAR << PAGE_SHIFT;
public static final int CALENDAR_TIME_ZONE = CALENDAR_PAGE + 5;
public static final int CALENDAR_ALL_DAY_EVENT = CALENDAR_PAGE + 6;
public static final int CALENDAR_ATTENDEES = CALENDAR_PAGE + 7;
public static final int CALENDAR_ATTENDEE = CALENDAR_PAGE + 8;
public static final int CALENDAR_ATTENDEE_EMAIL = CALENDAR_PAGE + 9;
public static final int CALENDAR_ATTENDEE_NAME = CALENDAR_PAGE + 0xA;
public static final int CALENDAR_BODY = CALENDAR_PAGE + 0xB;
public static final int CALENDAR_BODY_TRUNCATED = CALENDAR_PAGE + 0xC;
public static final int CALENDAR_BUSY_STATUS = CALENDAR_PAGE + 0xD;
public static final int CALENDAR_CATEGORIES = CALENDAR_PAGE + 0xE;
public static final int CALENDAR_CATEGORY = CALENDAR_PAGE + 0xF;
public static final int CALENDAR_COMPRESSED_RTF = CALENDAR_PAGE + 0x10;
public static final int CALENDAR_DTSTAMP = CALENDAR_PAGE + 0x11;
public static final int CALENDAR_END_TIME = CALENDAR_PAGE + 0x12;
public static final int CALENDAR_EXCEPTION = CALENDAR_PAGE + 0x13;
public static final int CALENDAR_EXCEPTIONS = CALENDAR_PAGE + 0x14;
public static final int CALENDAR_EXCEPTION_IS_DELETED = CALENDAR_PAGE + 0x15;
public static final int CALENDAR_EXCEPTION_START_TIME = CALENDAR_PAGE + 0x16;
public static final int CALENDAR_LOCATION = CALENDAR_PAGE + 0x17;
public static final int CALENDAR_MEETING_STATUS = CALENDAR_PAGE + 0x18;
public static final int CALENDAR_ORGANIZER_EMAIL = CALENDAR_PAGE + 0x19;
public static final int CALENDAR_ORGANIZER_NAME = CALENDAR_PAGE + 0x1A;
public static final int CALENDAR_RECURRENCE = CALENDAR_PAGE + 0x1B;
public static final int CALENDAR_RECURRENCE_TYPE = CALENDAR_PAGE + 0x1C;
public static final int CALENDAR_RECURRENCE_UNTIL = CALENDAR_PAGE + 0x1D;
public static final int CALENDAR_RECURRENCE_OCCURRENCES = CALENDAR_PAGE + 0x1E;
public static final int CALENDAR_RECURRENCE_INTERVAL = CALENDAR_PAGE + 0x1F;
public static final int CALENDAR_RECURRENCE_DAYOFWEEK = CALENDAR_PAGE + 0x20;
public static final int CALENDAR_RECURRENCE_DAYOFMONTH = CALENDAR_PAGE + 0x21;
public static final int CALENDAR_RECURRENCE_WEEKOFMONTH = CALENDAR_PAGE + 0x22;
public static final int CALENDAR_RECURRENCE_MONTHOFYEAR = CALENDAR_PAGE + 0x23;
public static final int CALENDAR_REMINDER_MINS_BEFORE = CALENDAR_PAGE + 0x24;
public static final int CALENDAR_SENSITIVITY = CALENDAR_PAGE + 0x25;
public static final int CALENDAR_SUBJECT = CALENDAR_PAGE + 0x26;
public static final int CALENDAR_START_TIME = CALENDAR_PAGE + 0x27;
public static final int CALENDAR_UID = CALENDAR_PAGE + 0x28;
public static final int CALENDAR_ATTENDEE_STATUS = CALENDAR_PAGE + 0x29;
public static final int CALENDAR_ATTENDEE_TYPE = CALENDAR_PAGE + 0x2A;
public static final int FOLDER_PAGE = FOLDER << PAGE_SHIFT;
public static final int FOLDER_FOLDERS = FOLDER_PAGE + 5;
public static final int FOLDER_FOLDER = FOLDER_PAGE + 6;
public static final int FOLDER_DISPLAY_NAME = FOLDER_PAGE + 7;
public static final int FOLDER_SERVER_ID = FOLDER_PAGE + 8;
public static final int FOLDER_PARENT_ID = FOLDER_PAGE + 9;
public static final int FOLDER_TYPE = FOLDER_PAGE + 0xA;
public static final int FOLDER_RESPONSE = FOLDER_PAGE + 0xB;
public static final int FOLDER_STATUS = FOLDER_PAGE + 0xC;
public static final int FOLDER_CONTENT_CLASS = FOLDER_PAGE + 0xD;
public static final int FOLDER_CHANGES = FOLDER_PAGE + 0xE;
public static final int FOLDER_ADD = FOLDER_PAGE + 0xF;
public static final int FOLDER_DELETE = FOLDER_PAGE + 0x10;
public static final int FOLDER_UPDATE = FOLDER_PAGE + 0x11;
public static final int FOLDER_SYNC_KEY = FOLDER_PAGE + 0x12;
public static final int FOLDER_FOLDER_CREATE = FOLDER_PAGE + 0x13;
public static final int FOLDER_FOLDER_DELETE= FOLDER_PAGE + 0x14;
public static final int FOLDER_FOLDER_UPDATE = FOLDER_PAGE + 0x15;
public static final int FOLDER_FOLDER_SYNC = FOLDER_PAGE + 0x16;
public static final int FOLDER_COUNT = FOLDER_PAGE + 0x17;
public static final int FOLDER_VERSION = FOLDER_PAGE + 0x18;
public static final int EMAIL_PAGE = EMAIL << PAGE_SHIFT;
public static final int EMAIL_ATTACHMENT = EMAIL_PAGE + 5;
public static final int EMAIL_ATTACHMENTS = EMAIL_PAGE + 6;
public static final int EMAIL_ATT_NAME = EMAIL_PAGE + 7;
public static final int EMAIL_ATT_SIZE = EMAIL_PAGE + 8;
public static final int EMAIL_ATT0ID = EMAIL_PAGE + 9;
public static final int EMAIL_ATT_METHOD = EMAIL_PAGE + 0xA;
public static final int EMAIL_ATT_REMOVED = EMAIL_PAGE + 0xB;
public static final int EMAIL_BODY = EMAIL_PAGE + 0xC;
public static final int EMAIL_BODY_SIZE = EMAIL_PAGE + 0xD;
public static final int EMAIL_BODY_TRUNCATED = EMAIL_PAGE + 0xE;
public static final int EMAIL_DATE_RECEIVED = EMAIL_PAGE + 0xF;
public static final int EMAIL_DISPLAY_NAME = EMAIL_PAGE + 0x10;
public static final int EMAIL_DISPLAY_TO = EMAIL_PAGE + 0x11;
public static final int EMAIL_IMPORTANCE = EMAIL_PAGE + 0x12;
public static final int EMAIL_MESSAGE_CLASS = EMAIL_PAGE + 0x13;
public static final int EMAIL_SUBJECT = EMAIL_PAGE + 0x14;
public static final int EMAIL_READ = EMAIL_PAGE + 0x15;
public static final int EMAIL_TO = EMAIL_PAGE + 0x16;
public static final int EMAIL_CC = EMAIL_PAGE + 0x17;
public static final int EMAIL_FROM = EMAIL_PAGE + 0x18;
public static final int EMAIL_REPLY_TO = EMAIL_PAGE + 0x19;
public static final int EMAIL_ALL_DAY_EVENT = EMAIL_PAGE + 0x1A;
public static final int EMAIL_CATEGORIES = EMAIL_PAGE + 0x1B;
public static final int EMAIL_CATEGORY = EMAIL_PAGE + 0x1C;
public static final int EMAIL_DTSTAMP = EMAIL_PAGE + 0x1D;
public static final int EMAIL_END_TIME = EMAIL_PAGE + 0x1E;
public static final int EMAIL_INSTANCE_TYPE = EMAIL_PAGE + 0x1F;
public static final int EMAIL_INTD_BUSY_STATUS = EMAIL_PAGE + 0x20;
public static final int EMAIL_LOCATION = EMAIL_PAGE + 0x21;
public static final int EMAIL_MEETING_REQUEST = EMAIL_PAGE + 0x22;
public static final int EMAIL_ORGANIZER = EMAIL_PAGE + 0x23;
public static final int EMAIL_RECURRENCE_ID = EMAIL_PAGE + 0x24;
public static final int EMAIL_REMINDER = EMAIL_PAGE + 0x25;
public static final int EMAIL_RESPONSE_REQUESTED = EMAIL_PAGE + 0x26;
public static final int EMAIL_RECURRENCES = EMAIL_PAGE + 0x27;
public static final int EMAIL_RECURRENCE = EMAIL_PAGE + 0x28;
public static final int EMAIL_RECURRENCE_TYPE = EMAIL_PAGE + 0x29;
public static final int EMAIL_RECURRENCE_UNTIL = EMAIL_PAGE + 0x2A;
public static final int EMAIL_RECURRENCE_OCCURRENCES = EMAIL_PAGE + 0x2B;
public static final int EMAIL_RECURRENCE_INTERVAL = EMAIL_PAGE + 0x2C;
public static final int EMAIL_RECURRENCE_DAYOFWEEK = EMAIL_PAGE + 0x2D;
public static final int EMAIL_RECURRENCE_DAYOFMONTH = EMAIL_PAGE + 0x2E;
public static final int EMAIL_RECURRENCE_WEEKOFMONTH = EMAIL_PAGE + 0x2F;
public static final int EMAIL_RECURRENCE_MONTHOFYEAR = EMAIL_PAGE + 0x30;
public static final int EMAIL_START_TIME = EMAIL_PAGE + 0x31;
public static final int EMAIL_SENSITIVITY = EMAIL_PAGE + 0x32;
public static final int EMAIL_TIME_ZONE = EMAIL_PAGE + 0x33;
public static final int EMAIL_GLOBAL_OBJID = EMAIL_PAGE + 0x34;
public static final int EMAIL_THREAD_TOPIC = EMAIL_PAGE + 0x35;
public static final int EMAIL_MIME_DATA = EMAIL_PAGE + 0x36;
public static final int EMAIL_MIME_TRUNCATED = EMAIL_PAGE + 0x37;
public static final int EMAIL_MIME_SIZE = EMAIL_PAGE + 0x38;
public static final int EMAIL_INTERNET_CPID = EMAIL_PAGE + 0x39;
public static final int EMAIL_FLAG = EMAIL_PAGE + 0x3A;
public static final int EMAIL_FLAG_STATUS = EMAIL_PAGE + 0x3B;
public static final int EMAIL_CONTENT_CLASS = EMAIL_PAGE + 0x3C;
public static final int EMAIL_FLAG_TYPE = EMAIL_PAGE + 0x3D;
public static final int EMAIL_COMPLETE_TIME = EMAIL_PAGE + 0x3E;
public static final int MOVE_PAGE = MOVE << PAGE_SHIFT;
public static final int MOVE_MOVE_ITEMS = MOVE_PAGE + 5;
public static final int MOVE_MOVE = MOVE_PAGE + 6;
public static final int MOVE_SRCMSGID = MOVE_PAGE + 7;
public static final int MOVE_SRCFLDID = MOVE_PAGE + 8;
public static final int MOVE_DSTFLDID = MOVE_PAGE + 9;
public static final int MOVE_RESPONSE = MOVE_PAGE + 0xA;
public static final int MOVE_STATUS = MOVE_PAGE + 0xB;
public static final int MOVE_DSTMSGID = MOVE_PAGE + 0xC;
public static final int CONTACTS2_PAGE = CONTACTS2 << PAGE_SHIFT;
public static final int CONTACTS2_CUSTOMER_ID = CONTACTS2_PAGE + 5;
public static final int CONTACTS2_GOVERNMENT_ID = CONTACTS2_PAGE + 6;
public static final int CONTACTS2_IM_ADDRESS = CONTACTS2_PAGE + 7;
public static final int CONTACTS2_IM_ADDRESS_2 = CONTACTS2_PAGE + 8;
public static final int CONTACTS2_IM_ADDRESS_3 = CONTACTS2_PAGE + 9;
public static final int CONTACTS2_MANAGER_NAME = CONTACTS2_PAGE + 0xA;
public static final int CONTACTS2_COMPANY_MAIN_PHONE = CONTACTS2_PAGE + 0xB;
public static final int CONTACTS2_ACCOUNT_NAME = CONTACTS2_PAGE + 0xC;
public static final int CONTACTS2_NICKNAME = CONTACTS2_PAGE + 0xD;
public static final int CONTACTS2_MMS = CONTACTS2_PAGE + 0xE;
// The Ping constants are used by EasSyncService, and need to be public
public static final int PING_PAGE = PING << PAGE_SHIFT;
public static final int PING_PING = PING_PAGE + 5;
public static final int PING_AUTD_STATE = PING_PAGE + 6;
public static final int PING_STATUS = PING_PAGE + 7;
public static final int PING_HEARTBEAT_INTERVAL = PING_PAGE + 8;
public static final int PING_FOLDERS = PING_PAGE + 9;
public static final int PING_FOLDER = PING_PAGE + 0xA;
public static final int PING_ID = PING_PAGE + 0xB;
public static final int PING_CLASS = PING_PAGE + 0xC;
public static final int PING_MAX_FOLDERS = PING_PAGE + 0xD;
public static final int BASE_PAGE = BASE << PAGE_SHIFT;
public static final int BASE_BODY_PREFERENCE = BASE_PAGE + 5;
public static final int BASE_TYPE = BASE_PAGE + 6;
public static final int BASE_TRUNCATION_SIZE = BASE_PAGE + 7;
public static final int BASE_ALL_OR_NONE = BASE_PAGE + 8;
public static final int BASE_RESERVED = BASE_PAGE + 9;
public static final int BASE_BODY = BASE_PAGE + 0xA;
public static final int BASE_DATA = BASE_PAGE + 0xB;
public static final int BASE_ESTIMATED_DATA_SIZE = BASE_PAGE + 0xC;
public static final int BASE_TRUNCATED = BASE_PAGE + 0xD;
public static final int BASE_ATTACHMENTS = BASE_PAGE + 0xE;
public static final int BASE_ATTACHMENT = BASE_PAGE + 0xF;
public static final int BASE_DISPLAY_NAME = BASE_PAGE + 0x10;
public static final int BASE_FILE_REFERENCE = BASE_PAGE + 0x11;
public static final int BASE_METHOD = BASE_PAGE + 0x12;
public static final int BASE_CONTENT_ID = BASE_PAGE + 0x13;
public static final int BASE_CONTENT_LOCATION = BASE_PAGE + 0x14;
public static final int BASE_IS_INLINE = BASE_PAGE + 0x15;
public static final int BASE_NATIVE_BODY_TYPE = BASE_PAGE + 0x16;
public static final int BASE_CONTENT_TYPE = BASE_PAGE + 0x17;
static public String[][] pages = {
{ // 0x00 AirSync
"Sync", "Responses", "Add", "Change", "Delete", "Fetch", "SyncKey", "ClientId",
"ServerId", "Status", "Collection", "Class", "Version", "CollectionId", "GetChanges",
"MoreAvailable", "WindowSize", "Commands", "Options", "FilterType", "Truncation",
"RTFTruncation", "Conflict", "Collections", "ApplicationData", "DeletesAsMoves",
"NotifyGUID", "Supported", "SoftDelete", "MIMESupport", "MIMETruncation", "Wait",
"Limit", "Partial"
},
{
// 0x01 Contacts
"Anniversary", "AssistantName", "AssistantTelephoneNumber", "Birthday", "ContactsBody",
"ContactsBodySize", "ContactsBodyTruncated", "Business2TelephoneNumber",
"BusinessAddressCity",
"BusinessAddressCountry", "BusinessAddressPostalCode", "BusinessAddressState",
"BusinessAddressStreet", "BusinessFaxNumber", "BusinessTelephoneNumber",
"CarTelephoneNumber", "ContactsCategories", "ContactsCategory", "Children", "Child",
"CompanyName", "Department", "Email1Address", "Email2Address", "Email3Address",
"FileAs", "FirstName", "Home2TelephoneNumber", "HomeAddressCity", "HomeAddressCountry",
"HomeAddressPostalCode", "HomeAddressState", "HomeAddressStreet", "HomeFaxNumber",
"HomeTelephoneNumber", "JobTitle", "LastName", "MiddleName", "MobileTelephoneNumber",
"OfficeLocation", "OtherAddressCity", "OtherAddressCountry",
"OtherAddressPostalCode", "OtherAddressState", "OtherAddressStreet", "PagerNumber",
"RadioTelephoneNumber", "Spouse", "Suffix", "Title", "Webpage", "YomiCompanyName",
"YomiFirstName", "YomiLastName", "CompressedRTF", "Picture"
},
{
// 0x02 Email
"Attachment", "Attachments", "AttName", "AttSize", "Add0Id", "AttMethod", "AttRemoved",
"Body", "BodySize", "BodyTruncated", "DateReceived", "DisplayName", "DisplayTo",
"Importance", "MessageClass", "Subject", "Read", "To", "CC", "From", "ReplyTo",
"AllDayEvent", "Categories", "Category", "DTStamp", "EndTime", "InstanceType",
"IntDBusyStatus", "Location", "MeetingRequest", "Organizer", "RecurrenceId", "Reminder",
"ResponseRequested", "Recurrences", "Recurence", "Recurrence_Type", "Recurrence_Until",
"Recurrence_Occurrences", "Recurrence_Interval", "Recurrence_DayOfWeek",
"Recurrence_DayOfMonth", "Recurrence_WeekOfMonth", "Recurrence_MonthOfYear",
"StartTime", "Sensitivity", "TimeZone", "GlobalObjId", "ThreadTopic", "MIMEData",
"MIMETruncated", "MIMESize", "InternetCPID", "Flag", "FlagStatus", "EmailContentClass",
"FlagType", "CompleteTime"
},
{
// 0x03 AirNotify
},
{
// 0x04 Calendar
"CalTimeZone", "CalAllDayEvent", "CalAttendees", "CalAttendee", "CalAttendee_Email",
"CalAttendee_Name", "CalBody", "CalBodyTruncated", "CalBusyStatus", "CalCategories",
"CalCategory", "CalCompressed_RTF", "CalDTStamp", "CalEndTime", "CalExeption",
"CalExceptions", "CalException_IsDeleted", "CalException_StartTime", "CalLocation",
"CalMeetingStatus", "CalOrganizer_Email", "CalOrganizer_Name", "CalRecurrence",
"CalRecurrence_Type", "CalRecurrence_Until", "CalRecurrence_Occurrences",
"CalRecurrence_Interval", "CalRecurrence_DayOfWeek", "CalRecurrence_DayOfMonth",
"CalRecurrence_WeekOfMonth", "CalRecurrence_MonthOfYear", "CalReminder_MinsBefore",
"CalSensitivity", "CalSubject", "CalStartTime", "CalUID", "CalAttendee_Status",
"CalAttendee_Type"
},
{
// 0x05 Move
"MoveItems", "Move", "SrcMsgId", "SrcFldId", "DstFldId", "MoveResponse", "MoveStatus",
"DstMsgId"
},
{
// 0x06 ItemEstimate
},
{
// 0x07 FolderHierarchy
"Folders", "Folder", "FolderDisplayName", "FolderServerId", "FolderParentId", "Type",
"FolderResponse", "FolderStatus", "FolderContentClass", "Changes", "FolderAdd",
"FolderDelete", "FolderUpdate", "FolderSyncKey", "FolderFolderCreate",
"FolderFolderDelete", "FolderFolderUpdate", "FolderSync", "Count", "FolderVersion"
},
{
// 0x08 MeetingResponse
},
{
// 0x09 Tasks
},
{
// 0x0A ResolveRecipients
},
{
// 0x0B ValidateCert
},
{
// 0x0C Contacts2
"CustomerId", "GovernmentId", "IMAddress", "IMAddress2", "IMAddress3", "ManagerName",
"CompanyMainPhone", "AccountName", "NickName", "MMS"
},
{
// 0x0D Ping
"Ping", "AutdState", "PingStatus", "HeartbeatInterval", "PingFolders", "PingFolder",
"PingId", "PingClass", "MaxFolders"
},
{
// 0x0E Provision
"Provision", "Policies", "Policy", "PolicyType", "PolicyKey", "Data", "ProvisionStatus",
"RemoteWipe", "EASProvidionDoc", "DevicePasswordEnabled",
"AlphanumericDevicePasswordRequired",
"DeviceEncryptionEnabled", "-unused-", "AttachmentsEnabled", "MinDevicePasswordLength",
"MaxInactivityTimeDeviceLock", "MaxDevicePasswordFailedAttempts", "MaxAttachmentSize",
"AllowSimpleDevicePassword", "DevicePasswordExpiration", "DevicePasswordHistory",
"AllowStorageCard", "AllowCamera", "RequireDeviceEncryption",
"AllowUnsignedApplications", "AllowUnsignedInstallationPackages",
"MinDevicePasswordComplexCharacters", "AllowWiFi", "AllowTextMessaging",
"AllowPOPIMAPEmail", "AllowBluetooth", "AllowIrDA", "RequireManualSyncWhenRoaming",
"AllowDesktopSync",
"MaxCalendarAgeFilder", "AllowHTMLEmail", "MaxEmailAgeFilder",
"MaxEmailBodyTruncationSize", "MaxEmailHTMLBodyTruncationSize",
"RequireSignedSMIMEMessages", "RequireEncryptedSMIMEMessages",
"RequireSignedSMIMEAlgorithm", "RequireEncryptionSMIMEAlgorithm",
"AllowSMIMEEncryptionAlgorithmNegotiation", "AllowSMIMESoftCerts", "AllowBrowser",
"AllowConsumerEmail", "AllowRemoteDesktop", "AllowInternetSharing",
"UnapprovedInROMApplicationList", "ApplicationName", "ApprovedApplicationList", "Hash"
},
{
// 0x0F Search
},
{
// 0x10 Gal
"GalDisplayName", "GalPhone", "GalOffice", "GalTitle", "GalCompany", "GalAlias",
"GalFirstName", "GalLastName", "GalHomePhone", "GalMobilePhone", "GalEmailAddress"
},
{
// 0x11 AirSyncBase
"BodyPreference", "BodyPreferenceType", "BodyPreferenceTruncationSize", "AllOrNone",
"--unused--", "BaseBody", "BaseData", "BaseEstimatedDataSize", "BaseTruncated",
"BaseAttachments", "BaseAttachment", "BaseDisplayName", "FileReference", "BaseMethod",
"BaseContentId", "BaseContentLocation", "BaseIsInline", "BaseNativeBodyType",
"BaseContentType"
},
{
// 0x12 Settings
},
{
// 0x13 DocumentLibrary
},
{
// 0x14 ItemOperations
}
};
}

View File

@ -18,8 +18,8 @@ package com.android.exchange;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.exchange.adapter.EasEmailSyncAdapter;
import com.android.exchange.adapter.EasEmailSyncAdapter.EasEmailSyncParser;
import com.android.exchange.adapter.EmailSyncAdapter;
import com.android.exchange.adapter.EmailSyncAdapter.EasEmailSyncParser;
import android.test.AndroidTestCase;
@ -51,7 +51,7 @@ public class EasEmailSyncAdapterTests extends AndroidTestCase {
service.mContext = getContext();
service.mMailbox = mailbox;
service.mAccount = account;
EasEmailSyncAdapter adapter = new EasEmailSyncAdapter(mailbox, service);
EmailSyncAdapter adapter = new EmailSyncAdapter(mailbox, service);
EasEmailSyncParser p;
p = adapter.new EasEmailSyncParser(getTestInputStream(), service);
// Test a few known types

View File

@ -16,24 +16,17 @@
package com.android.exchange;
import com.android.email.provider.EmailContent.Account;
import com.android.email.provider.EmailContent.Mailbox;
import com.android.exchange.adapter.EasEmailSyncAdapter;
import com.android.exchange.adapter.EasTags;
import com.android.exchange.adapter.EasEmailSyncAdapter.EasEmailSyncParser;
import com.android.exchange.adapter.Tags;
import android.test.AndroidTestCase;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
public class EasTagsTests extends AndroidTestCase {
public class TagsTests extends AndroidTestCase {
// Make sure there are no duplicates in the tags table
public void testNoDuplicates() {
String[][] allTags = EasTags.pages;
String[][] allTags = Tags.pages;
HashMap<String, Boolean> map = new HashMap<String, Boolean>();
for (String[] page: allTags) {
for (String tag: page) {