EmailSyncAdapterService.java revision 328ca0d959f7e729e96f19538c8f3af8fe782a09
12674530d1879be7ae2df5105f07a93a5557ec389Marc Blank/* 22674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * Copyright (C) 2010 The Android Open Source Project 32674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * 42674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * Licensed under the Apache License, Version 2.0 (the "License"); 52674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * you may not use this file except in compliance with the License. 62674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * You may obtain a copy of the License at 72674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * 82674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * http://www.apache.org/licenses/LICENSE-2.0 92674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * 102674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * Unless required by applicable law or agreed to in writing, software 112674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * distributed under the License is distributed on an "AS IS" BASIS, 122674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * See the License for the specific language governing permissions and 142674530d1879be7ae2df5105f07a93a5557ec389Marc Blank * limitations under the License. 152674530d1879be7ae2df5105f07a93a5557ec389Marc Blank */ 162674530d1879be7ae2df5105f07a93a5557ec389Marc Blank 17bbafcf7dbcb92063aa207113451c1d29235bc5ddMarc Blankpackage com.android.exchange.service; 182674530d1879be7ae2df5105f07a93a5557ec389Marc Blank 19ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.content.AbstractThreadedSyncAdapter; 20ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.content.ContentProviderClient; 21ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.content.ContentResolver; 22e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Huimport android.content.ContentValues; 23ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.content.Context; 24ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.content.Intent; 25ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.content.SyncResult; 26ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.database.Cursor; 27ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Huimport android.os.AsyncTask; 28ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.os.Bundle; 29ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Huimport android.os.IBinder; 30ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu 315f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport com.android.emailcommon.Api; 32bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Huimport com.android.emailcommon.TempDirectory; 33c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Huimport com.android.emailcommon.provider.Account; 34bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Huimport com.android.emailcommon.provider.EmailContent; 35c8e4352ea6cfa67f15140512e84af8ccede222d2Marc Blankimport com.android.emailcommon.provider.EmailContent.AccountColumns; 365f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport com.android.emailcommon.provider.HostAuth; 374d8774462ace9a45154b2df418b9f2fe7a9c685dBen Komaloimport com.android.emailcommon.provider.Mailbox; 385f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport com.android.emailcommon.service.IEmailService; 395f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport com.android.emailcommon.service.IEmailServiceCallback; 405f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport com.android.emailcommon.service.SearchParams; 41bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Huimport com.android.emailcommon.utility.Utility; 425f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport com.android.exchange.Eas; 43ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Huimport com.android.exchange.adapter.PingParser; 44b3ee6545d55cd02161cb8acf054f3edbec02dacfPaul Westbrookimport com.android.exchange.adapter.Search; 45328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Huimport com.android.exchange.eas.EasFolderSync; 46ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Huimport com.android.exchange.eas.EasOperation; 47ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Huimport com.android.exchange.eas.EasPing; 485f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport com.android.mail.providers.UIProvider.AccountCapabilities; 49942b7d73f2f5b3d6c651e39463e615fe6902a910Scott Kennedyimport com.android.mail.utils.LogUtils; 505f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 515f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Huimport java.util.HashMap; 522674530d1879be7ae2df5105f07a93a5557ec389Marc Blank 532177272932413dd434ed1a393b22f452dc38740aYu Ping Hu/** 542177272932413dd434ed1a393b22f452dc38740aYu Ping Hu * Service for communicating with Exchange servers. There are three main parts of this class: 552177272932413dd434ed1a393b22f452dc38740aYu Ping Hu * TODO: Flesh out these comments. 562177272932413dd434ed1a393b22f452dc38740aYu Ping Hu * 1) An {@link AbstractThreadedSyncAdapter} to handle actually performing syncs. 572177272932413dd434ed1a393b22f452dc38740aYu Ping Hu * 2) Bookkeeping for running Ping requests, which handles push notifications. 582177272932413dd434ed1a393b22f452dc38740aYu Ping Hu * 3) An {@link IEmailService} Stub to handle RPC from the UI. 592177272932413dd434ed1a393b22f452dc38740aYu Ping Hu */ 60bbafcf7dbcb92063aa207113451c1d29235bc5ddMarc Blankpublic class EmailSyncAdapterService extends AbstractSyncAdapterService { 615f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 6287aa63eab6bb5abe86746d3f60c7ea1847393003Paul Westbrook private static final String TAG = "EASEmailSyncAdaptSvc"; 635f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 645f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 65456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu * If sync extras do not include a mailbox id, then we want to perform a full sync. 66456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu */ 67456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu private static final long FULL_ACCOUNT_SYNC = Mailbox.NO_MAILBOX; 68456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu 69ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu /** Projection used for getting email address for an account. */ 70ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu private static final String[] ACCOUNT_EMAIL_PROJECTION = { AccountColumns.EMAIL_ADDRESS }; 71ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu 72456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu /** 735f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * Bookkeeping for handling synchronization between pings and syncs. 745f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * "Ping" refers to a hanging POST or GET that is used to receive push notifications. Ping is 755f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * the term for the Exchange command, but this code should be generic enough to be easily 765f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * extended to IMAP. 775f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * "Sync" refers to an actual sync command to either fetch mail state, account state, or send 785f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * mail (send is implemented as "sync the outbox"). 795f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * TODO: Outbox sync probably need not stop a ping in progress. 805f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * Basic rules of how these interact (note that all rules are per account): 815f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - Only one ping or sync may run at a time. 825f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - Due to how {@link AbstractThreadedSyncAdapter} works, sync requests will not occur while 835f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * a sync is in progress. 845f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - On the other hand, ping requests may come in while handling a ping. 855f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - "Ping request" is shorthand for "a request to change our ping parameters", which includes 865f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * a request to stop receiving push notifications. 875f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - If neither a ping nor a sync is running, then a request for either will run it. 885f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - If a sync is running, new ping requests block until the sync completes. 895f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - If a ping is running, a new sync request stops the ping and creates a pending ping 905f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * (which blocks until the sync completes). 915f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - If a ping is running, a new ping request stops the ping and either starts a new one or 925f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * does nothing, as appopriate (since a ping request can be to stop pushing). 935f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * - As an optimization, while a ping request is waiting to run, subsequent ping requests are 945f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * ignored (the pending ping will pick up the latest ping parameters at the time it runs). 955f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 96400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu public class SyncHandlerSynchronizer { 975f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 985f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * Map of account id -> ping handler. 995f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * For a given account id, there are three possible states: 1005f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * 1) If no ping or sync is currently running, there is no entry in the map for the account. 1015f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * 2) If a ping is running, there is an entry with the appropriate ping handler. 1025f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * 3) If there is a sync running, there is an entry with null as the value. 1035f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * We cannot have more than one ping or sync running at a time. 1045f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 105ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu private final HashMap<Long, PingTask> mPingHandlers = new HashMap<Long, PingTask>(); 1065f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 1075f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 1085f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * Wait until neither a sync nor a ping is running on this account, and then return. 1095f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * If there's a ping running, actively stop it. (For syncs, we have to just wait.) 1105f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * @param accountId The account we want to wait for. 1115f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 1125f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu private synchronized void waitUntilNoActivity(final long accountId) { 1135f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu while (mPingHandlers.containsKey(accountId)) { 114ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu final PingTask pingHandler = mPingHandlers.get(accountId); 1155f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu if (pingHandler != null) { 116ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu pingHandler.stop(); 1175f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1185f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu try { 1195f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu wait(); 120ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } catch (final InterruptedException e) { 1215f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // TODO: When would this happen, and how should I handle it? 1225f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1235f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1245f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1255f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 1265f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 1275f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * Use this to see if we're currently syncing, as opposed to pinging or doing nothing. 1285f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * @param accountId The account to check. 1295f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * @return Whether that account is currently running a sync. 1305f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 1315f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu private synchronized boolean isRunningSync(final long accountId) { 1325f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return (mPingHandlers.containsKey(accountId) && mPingHandlers.get(accountId) == null); 1335f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1345f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 135ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu /** 136ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * If there are no running pings, stop the service. 137ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu */ 138400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu private void stopServiceIfNoPings() { 139ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu for (final PingTask pingHandler : mPingHandlers.values()) { 140400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu if (pingHandler != null) { 141400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu return; 142400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu } 143400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu } 144400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu EmailSyncAdapterService.this.stopSelf(); 145400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu } 146400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu 1475f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 148ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * Called prior to starting a sync to update our bookkeeping. We don't actually run the sync 149ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * here; the caller must do that. 1505f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * @param accountId The account on which we are running a sync. 1515f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 1525f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public synchronized void startSync(final long accountId) { 1535f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu waitUntilNoActivity(accountId); 1545f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu mPingHandlers.put(accountId, null); 1555f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1565f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 1575f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 158ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * Starts or restarts a ping for an account, if the current account state indicates that it 159ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * wants to push. 160ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * @param account The account whose ping is being modified. 1615f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 162ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu public synchronized void modifyPing(final Account account) { 163ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // If a sync is currently running, it will start a ping when it's done, so there's no 164ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // need to do anything right now. 165ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu if (isRunningSync(account.mId)) { 1665f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return; 1675f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1685f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 169ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // If a ping is currently running, tell it to restart to pick up new params. 170ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu final PingTask pingSyncHandler = mPingHandlers.get(account.mId); 171ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu if (pingSyncHandler != null) { 172ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu pingSyncHandler.restart(); 1735f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return; 1745f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1755f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 176ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // If we're here, then there's neither a sync nor a ping running. Start a new ping. 177ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu final EmailSyncAdapterService service = EmailSyncAdapterService.this; 178ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu if (account.mSyncInterval == Account.CHECK_INTERVAL_PUSH) { 179ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu // TODO: Also check if we have any mailboxes that WANT push. 180ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // This account needs to ping. 181ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // Note: unlike startSync, we CANNOT allow the caller to do the actual work. 182ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // If we return before the ping starts, there's a race condition where another 183ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // ping or sync might start first. It only works for startSync because sync is 184ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // higher priority than ping (i.e. a ping can't start while a sync is pending) 185ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // and only one sync can run at a time. 186ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu final PingTask pingHandler = new PingTask(service, account, this); 187ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu mPingHandlers.put(account.mId, pingHandler); 188ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu pingHandler.start(); 189ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // Whenever we have a running ping, make sure this service stays running. 190ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu service.startService(new Intent(service, EmailSyncAdapterService.class)); 1915f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1925f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 1935f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 1945f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 195ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * Updates the synchronization bookkeeping when a sync is done. 196ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * @param account The account whose sync just finished. 1975f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 198ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu public synchronized void syncComplete(final Account account) { 199ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu mPingHandlers.remove(account.mId); 200ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // Syncs can interrupt pings, so we should check if we need to start one now. 201ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu modifyPing(account); 202ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu stopServiceIfNoPings(); 203ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu notifyAll(); 204ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 205ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 206ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu /** 207ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * Updates the synchronization bookkeeping when a ping is done. Also requests a ping-only 208ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * sync if necessary. 209ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * @param amAccount The {@link android.accounts.Account} for this account. 210ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu * @param accountId The account whose ping just finished. 211ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * @param pingStatus The status value from {@link PingParser} for the last ping performed. 212ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * This cannot be one of the values that results in another ping, so this 213ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * function only needs to handle the terminal statuses. 214ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu */ 215ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu public synchronized void pingComplete(final android.accounts.Account amAccount, 216ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu final long accountId, final int pingStatus) { 217ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu mPingHandlers.remove(accountId); 218ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 219ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // TODO: if (pingStatus == PingParser.STATUS_FAILED), notify UI. 220ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // TODO: if (pingStatus == PingParser.STATUS_REQUEST_TOO_MANY_FOLDERS), notify UI. 221ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 222ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu if (pingStatus == EasOperation.RESULT_REQUEST_FAILURE) { 223ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // Request a new ping through the SyncManager. This will do the right thing if the 224ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // exception was due to loss of network connectivity, etc. (i.e. it will wait for 225ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // network to restore and then request it). 226ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu EasPing.requestPing(amAccount); 227ff7e02603bc8196f411c0c491d74a42e747b7dc5Yu Ping Hu } else { 228400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu stopServiceIfNoPings(); 2295f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 2305f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 231ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // TODO: It might be the case that only STATUS_CHANGES_FOUND and 232ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // STATUS_FOLDER_REFRESH_NEEDED need to notifyAll(). Think this through. 233ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu notifyAll(); 2345f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 235ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 2365f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 237400d8d752257eb65632e8840f5912d933e386c99Yu Ping Hu private final SyncHandlerSynchronizer mSyncHandlerMap = new SyncHandlerSynchronizer(); 2385f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 2395f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 2405f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * The binder for IEmailService. 2415f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 2425f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu private final IEmailService.Stub mBinder = new IEmailService.Stub() { 243ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu 244ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu private String getEmailAddressForAccount(final long accountId) { 245ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu final String emailAddress = Utility.getFirstRowString(EmailSyncAdapterService.this, 246ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu Account.CONTENT_URI, ACCOUNT_EMAIL_PROJECTION, Account.ID_SELECTION, 247ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu new String[] {Long.toString(accountId)}, null, 0); 248ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu if (emailAddress == null) { 249ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu LogUtils.e(TAG, "Could not find email address for account %d", accountId); 250ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu } 251ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu return emailAddress; 252ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu } 253ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu 2545f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 2555f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public Bundle validate(final HostAuth hostAuth) { 256942b7d73f2f5b3d6c651e39463e615fe6902a910Scott Kennedy LogUtils.d(TAG, "IEmailService.validate"); 257bc278f1e81ef1d44c28093e830ebe84faa960843Yu Ping Hu return new EasAccountValidator(EmailSyncAdapterService.this, hostAuth).validate(); 2585f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 2595f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 2605f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 261ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu public Bundle autoDiscover(final String username, final String password) { 262942b7d73f2f5b3d6c651e39463e615fe6902a910Scott Kennedy LogUtils.d(TAG, "IEmailService.autoDiscover"); 263ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu return new EasAutoDiscover(EmailSyncAdapterService.this, username, password) 264ddbe7744f17d9dd0e26bc2d5a1e89aec9b031bddYu Ping Hu .doAutodiscover(); 2655f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 2665f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 2675f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 2685f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void updateFolderList(final long accountId) { 269ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu LogUtils.d(TAG, "IEmailService.updateFolderList: %d", accountId); 270ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu final String emailAddress = getEmailAddressForAccount(accountId); 271bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu if (emailAddress != null) { 272bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu ContentResolver.requestSync(new android.accounts.Account( 273bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu emailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), 274bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu EmailContent.AUTHORITY, new Bundle()); 275bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu } 2765f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 2775f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 2785f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 2795f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void setLogging(final int flags) { 2805f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // TODO: fix this? 2815f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // Protocol logging 2825f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu Eas.setUserDebug(flags); 2835f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // Sync logging 2845f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu //setUserDebug(flags); 2855f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 2865f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 2875f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 288359b3673e053a4f051997a809d8419c75f02c18bYu Ping Hu public void loadAttachment(final IEmailServiceCallback callback, final long attachmentId, 289359b3673e053a4f051997a809d8419c75f02c18bYu Ping Hu final boolean background) { 290c35d2fa94faa0f9abeded869a01108bac2bcedccYu Ping Hu LogUtils.d(TAG, "IEmailService.loadAttachment: %d", attachmentId); 291da835b7580108777bb0fa4a4d7287676a1cd7e53Yu Ping Hu // TODO: Prevent this from happening in parallel with a sync? 292da835b7580108777bb0fa4a4d7287676a1cd7e53Yu Ping Hu EasAttachmentLoader.loadAttachment(EmailSyncAdapterService.this, attachmentId, 293da835b7580108777bb0fa4a4d7287676a1cd7e53Yu Ping Hu callback); 2945f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 2955f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 2965f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 2975f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void sendMeetingResponse(final long messageId, final int response) { 29862c287af3bed45818accf595c56879ad5c57aaf9Yu Ping Hu LogUtils.d(TAG, "IEmailService.sendMeetingResponse: %d, %d", messageId, response); 29962c287af3bed45818accf595c56879ad5c57aaf9Yu Ping Hu EasMeetingResponder.sendMeetingResponse(EmailSyncAdapterService.this, messageId, 30062c287af3bed45818accf595c56879ad5c57aaf9Yu Ping Hu response); 3015f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3025f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3035f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu /** 3045f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * Delete PIM (calendar, contacts) data for the specified account 3055f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu * 306ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu * @param emailAddress the email address for the account whose data should be deleted 3075f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu */ 3085f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 309ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu public void deleteAccountPIMData(final String emailAddress) { 310942b7d73f2f5b3d6c651e39463e615fe6902a910Scott Kennedy LogUtils.d(TAG, "IEmailService.deleteAccountPIMData"); 311ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu if (emailAddress != null) { 312ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu final Context context = EmailSyncAdapterService.this; 313ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu EasContactsSyncHandler.wipeAccountFromContentProvider(context, emailAddress); 314ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu EasCalendarSyncHandler.wipeAccountFromContentProvider(context, emailAddress); 3155f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 316ea55e973f5820f03931143f8d2df413c70bf4284Yu Ping Hu // TODO: Run account reconciler? 3175f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3185f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3195f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3205f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public int searchMessages(final long accountId, final SearchParams searchParams, 3215f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu final long destMailboxId) { 322b3ee6545d55cd02161cb8acf054f3edbec02dacfPaul Westbrook LogUtils.d(TAG, "IEmailService.searchMessages"); 323b3ee6545d55cd02161cb8acf054f3edbec02dacfPaul Westbrook return Search.searchMessages(EmailSyncAdapterService.this, accountId, searchParams, 3245f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu destMailboxId); 325e2788afb86984dae29255fd9c7e24c78d90dbdadYu Ping Hu // TODO: may need an explicit callback to replace the one to IEmailServiceCallback. 3265f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3275f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3285f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3295f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void sendMail(final long accountId) {} 3305f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3315f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3325f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public int getCapabilities(final Account acct) { 3335f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu String easVersion = acct.mProtocolVersion; 3345f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu Double easVersionDouble = 2.5D; 3355f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu if (easVersion != null) { 3365f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu try { 3375f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu easVersionDouble = Double.parseDouble(easVersion); 3385f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } catch (NumberFormatException e) { 3395f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // Stick with 2.5 3405f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3415f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3425f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu if (easVersionDouble >= 12.0D) { 3435f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return AccountCapabilities.SYNCABLE_FOLDERS | 3445f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu AccountCapabilities.SERVER_SEARCH | 3455f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu AccountCapabilities.FOLDER_SERVER_SEARCH | 3465f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu AccountCapabilities.SANITIZED_HTML | 3475f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu AccountCapabilities.SMART_REPLY | 3485f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu AccountCapabilities.SERVER_SEARCH | 3495928ffc5b48ada2e0edb37d21c8c7c92b5b290b7Yu Ping Hu AccountCapabilities.UNDO | 3505928ffc5b48ada2e0edb37d21c8c7c92b5b290b7Yu Ping Hu AccountCapabilities.DISCARD_CONVERSATION_DRAFTS; 3515f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } else { 3525f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return AccountCapabilities.SYNCABLE_FOLDERS | 3535f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu AccountCapabilities.SANITIZED_HTML | 3545f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu AccountCapabilities.SMART_REPLY | 3555928ffc5b48ada2e0edb37d21c8c7c92b5b290b7Yu Ping Hu AccountCapabilities.UNDO | 3565928ffc5b48ada2e0edb37d21c8c7c92b5b290b7Yu Ping Hu AccountCapabilities.DISCARD_CONVERSATION_DRAFTS; 3575f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3585f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3595f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3605f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3615f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void serviceUpdated(final String emailAddress) { 3625f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // Not required for EAS 3635f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3645f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3655f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // All IEmailService messages below are UNCALLED in Email. 3665f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // TODO: Remove. 3675f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 3685f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3695f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public int getApiLevel() { 3705f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return Api.LEVEL; 3715f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3725f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3735f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 3745f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3755f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void startSync(long mailboxId, boolean userRequest, int deltaMessageCount) {} 3765f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3775f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 3785f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3795f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void stopSync(long mailboxId) {} 3805f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3815f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 3825f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3835f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void loadMore(long messageId) {} 3845f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3855f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 3865f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3875f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public boolean createFolder(long accountId, String name) { 3885f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return false; 3895f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3905f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3915f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 3925f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3935f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public boolean deleteFolder(long accountId, String name) { 3945f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return false; 3955f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 3965f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 3975f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 3985f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 3995f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public boolean renameFolder(long accountId, String oldName, String newName) { 4005f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return false; 4015f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 4025f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 4035f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Deprecated 4045f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 4055f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public void hostChanged(long accountId) {} 4065f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu }; 4075f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 4082674530d1879be7ae2df5105f07a93a5557ec389Marc Blank public EmailSyncAdapterService() { 4092674530d1879be7ae2df5105f07a93a5557ec389Marc Blank super(); 4102674530d1879be7ae2df5105f07a93a5557ec389Marc Blank } 4112674530d1879be7ae2df5105f07a93a5557ec389Marc Blank 412ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu /** 413ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu * {@link AsyncTask} for restarting pings for all accounts that need it. 414ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu */ 415ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu private static class RestartPingsTask extends AsyncTask<Void, Void, Void> { 416ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu private static final String PUSH_ACCOUNTS_SELECTION = 417ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu AccountColumns.SYNC_INTERVAL + "=" + Integer.toString(Account.CHECK_INTERVAL_PUSH); 418ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 419ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu private final ContentResolver mContentResolver; 420ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu private final SyncHandlerSynchronizer mSyncHandlerMap; 421ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 422ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu public RestartPingsTask(final ContentResolver contentResolver, 423ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu final SyncHandlerSynchronizer syncHandlerMap) { 424ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu mContentResolver = contentResolver; 425ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu mSyncHandlerMap = syncHandlerMap; 426ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 427ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 428ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu @Override 429ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu protected Void doInBackground(Void... params) { 430ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu final Cursor c = mContentResolver.query(Account.CONTENT_URI, 431ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu Account.CONTENT_PROJECTION, PUSH_ACCOUNTS_SELECTION, null, null); 432ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu if (c != null) { 433ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu try { 434ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu while (c.moveToNext()) { 435ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu final Account account = new Account(); 436ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu account.restore(c); 437ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu mSyncHandlerMap.modifyPing(account); 438ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 439ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } finally { 440ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu c.close(); 441ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 442ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 443ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu return null; 444ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 445ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 446ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 447ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu @Override 448ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu public void onCreate() { 449ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu super.onCreate(); 450ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // Restart push for all accounts that need it. 451ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu new RestartPingsTask(getContentResolver(), mSyncHandlerMap).executeOnExecutor( 452ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu AsyncTask.THREAD_POOL_EXECUTOR); 453ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 454ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 4559696d7f701599644d1c108863d6195af88da2c30Yu Ping Hu @Override 4565f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu public IBinder onBind(Intent intent) { 4575f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu if (intent.getAction().equals(Eas.EXCHANGE_SERVICE_INTENT_ACTION)) { 4585f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return mBinder; 4595f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 4605f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu return super.onBind(intent); 4615f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu } 4625f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 4635f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu @Override 4649696d7f701599644d1c108863d6195af88da2c30Yu Ping Hu protected AbstractThreadedSyncAdapter newSyncAdapter() { 4659696d7f701599644d1c108863d6195af88da2c30Yu Ping Hu return new SyncAdapterImpl(this); 4669696d7f701599644d1c108863d6195af88da2c30Yu Ping Hu } 4679696d7f701599644d1c108863d6195af88da2c30Yu Ping Hu 4685f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // TODO: Handle cancelSync() appropriately. 4695f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu private class SyncAdapterImpl extends AbstractThreadedSyncAdapter { 4702674530d1879be7ae2df5105f07a93a5557ec389Marc Blank public SyncAdapterImpl(Context context) { 4712674530d1879be7ae2df5105f07a93a5557ec389Marc Blank super(context, true /* autoInitialize */); 4722674530d1879be7ae2df5105f07a93a5557ec389Marc Blank } 4732674530d1879be7ae2df5105f07a93a5557ec389Marc Blank 4742674530d1879be7ae2df5105f07a93a5557ec389Marc Blank @Override 475456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu public void onPerformSync(final android.accounts.Account acct, final Bundle extras, 476456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu final String authority, final ContentProviderClient provider, 477456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu final SyncResult syncResult) { 478456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu LogUtils.i(TAG, "performSync: extras = %s", extras.toString()); 479bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu TempDirectory.setTempDirectory(EmailSyncAdapterService.this); 480bc96ce2b61336a99ce044dcb77d0c69ec9ddb718Yu Ping Hu 481c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // TODO: Perform any connectivity checks, bail early if we don't have proper network 482c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // for this sync operation. 4832674530d1879be7ae2df5105f07a93a5557ec389Marc Blank 484c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu final Context context = getContext(); 485c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu final ContentResolver cr = context.getContentResolver(); 486c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu 487c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // Get the EmailContent Account 488c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu final Account account; 489c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu final Cursor accountCursor = cr.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION, 490c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu AccountColumns.EMAIL_ADDRESS + "=?", new String[] {acct.name}, null); 4910b90e8d0cebf3e40c894f2e84b8cd3aa82d83765Yu Ping Hu try { 492c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu if (!accountCursor.moveToFirst()) { 493c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // Could not load account. 494c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // TODO: improve error handling. 495c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu return; 4962674530d1879be7ae2df5105f07a93a5557ec389Marc Blank } 497c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu account = new Account(); 498c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu account.restore(accountCursor); 4990b90e8d0cebf3e40c894f2e84b8cd3aa82d83765Yu Ping Hu } finally { 5000b90e8d0cebf3e40c894f2e84b8cd3aa82d83765Yu Ping Hu accountCursor.close(); 5012674530d1879be7ae2df5105f07a93a5557ec389Marc Blank } 502ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // Get the mailbox that we want to sync. 503ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // There are four possibilities for Mailbox.SYNC_EXTRA_MAILBOX_ID: 504ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // 1) Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY: Restart push if appropriate. 505ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // 2) Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY: Sync only the account data. 506ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // 3) Not present: Perform a full account sync. 507ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // 4) Non-negative value: It's an actual mailbox id, sync that mailbox only. 508ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu final long mailboxId = extras.getLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, FULL_ACCOUNT_SYNC); 509ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu 510ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // If we're just twiddling the push, we do the lightweight thing and just bail. 511ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu if (mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY) { 512ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu mSyncHandlerMap.modifyPing(account); 513ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu return; 514ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu } 515c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu 5165f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // Do the bookkeeping for starting a sync, including stopping a ping if necessary. 5175f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu mSyncHandlerMap.startSync(account.mId); 5185f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 5195f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // TODO: Should we refresh the account here? It may have changed while waiting for any 5205f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // pings to stop. It may not matter since the things that may have been twiddled might 5215f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu // not affect syncing. 5225f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 523456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu if (mailboxId == FULL_ACCOUNT_SYNC || 524456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY) { 525328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu final EasFolderSync folderSync = new EasFolderSync(context, account); 526328ca0d959f7e729e96f19538c8f3af8fe782a09Yu Ping Hu folderSync.doFolderSync(syncResult); 52740350a7cea38385bc47eec399ae0d08aeeb01620Yu Ping Hu 528ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu if (mailboxId == FULL_ACCOUNT_SYNC) { 529456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu // Full account sync includes all mailboxes that participate in system sync. 530456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu final Cursor c = Mailbox.getMailboxIdsForSync(cr, account.mId); 531456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu if (c != null) { 532456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu try { 533456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu while (c.moveToNext()) { 534456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu syncMailbox(context, cr, acct, account, c.getLong(0), extras, 535e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu syncResult, false); 536456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } 537456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } finally { 538456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu c.close(); 539456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } 540456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } 541c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu } 542c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu } else { 543c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // Sync the mailbox that was explicitly requested. 544e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu syncMailbox(context, cr, acct, account, mailboxId, extras, syncResult, true); 545c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu } 5465f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 547ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu // Clean up the bookkeeping, including restarting ping if necessary. 548ae6c69d73448bd4184724dfa351d17ca0cf378b2Yu Ping Hu mSyncHandlerMap.syncComplete(account); 5495f6b6438ebb60e3eb00731ab13083d393a302ed9Yu Ping Hu 550c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // TODO: It may make sense to have common error handling here. Two possible mechanisms: 551c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // 1) performSync return value can signal some useful info. 552c9e47f85203da0ea3b6e9a49aa2007d1fc6f0814Yu Ping Hu // 2) syncResult can contain useful info. 5532674530d1879be7ae2df5105f07a93a5557ec389Marc Blank } 554456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu 555e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu /** 556e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu * Update the mailbox's sync status with the provider and, if we're finished with the sync, 557e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu * write the last sync time as well. 558e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu * @param context Our {@link Context}. 559e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu * @param mailbox The mailbox whose sync status to update. 560e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu * @param cv A {@link ContentValues} object to use for updating the provider. 561e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu * @param syncStatus The status for the current sync. 562e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu */ 563e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu private void updateMailbox(final Context context, final Mailbox mailbox, 564e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu final ContentValues cv, final int syncStatus) { 565e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu cv.put(Mailbox.UI_SYNC_STATUS, syncStatus); 566e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu if (syncStatus == EmailContent.SYNC_STATUS_NONE) { 567e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu cv.put(Mailbox.SYNC_TIME, System.currentTimeMillis()); 568e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu } 569e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu mailbox.update(context, cv); 570e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu } 571e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu 572456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu private boolean syncMailbox(final Context context, final ContentResolver cr, 573456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu final android.accounts.Account acct, final Account account, final long mailboxId, 574e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu final Bundle extras, final SyncResult syncResult, final boolean isMailboxSync) { 575456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu final Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId); 576456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu if (mailbox == null) { 577456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu return false; 578456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } 579456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu 5805586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu final boolean success; 581e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu // Non-mailbox syncs are whole account syncs initiated by the AccountManager and are 582e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu // treated as background syncs. 583e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu // TODO: Push will be treated as "user" syncs, and probably should be background. 5845586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu final ContentValues cv = new ContentValues(2); 5855586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu updateMailbox(context, mailbox, cv, isMailboxSync ? 5865586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu EmailContent.SYNC_STATUS_USER : EmailContent.SYNC_STATUS_BACKGROUND); 587e2a704dca25a36ff177f9908b047602af8ddffe3Yu Ping Hu 588456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu if (mailbox.mType == Mailbox.TYPE_OUTBOX) { 589456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu final EasOutboxSyncHandler outboxSyncHandler = 590456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu new EasOutboxSyncHandler(context, account, mailbox); 591456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu outboxSyncHandler.performSync(); 5925586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu success = true; 5935586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu } else if(mailbox.isSyncable()) { 594456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu final EasSyncHandler syncHandler = EasSyncHandler.getEasSyncHandler(context, cr, 595456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu acct, account, mailbox, extras, syncResult); 5965586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu success = (syncHandler != null); 5975586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu if (syncHandler != null) { 5985586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu syncHandler.performSync(); 599456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } 6005586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu } else { 6015586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu success = false; 602456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } 6035586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu updateMailbox(context, mailbox, cv, EmailContent.SYNC_STATUS_NONE); 6045586f9f5ab654ca93d797fa2a8cbc78a8d6970a4Yu Ping Hu return success; 605456a6e3e01205e8c779930d8c7533b1c7467df5eYu Ping Hu } 6062674530d1879be7ae2df5105f07a93a5557ec389Marc Blank } 6070b90e8d0cebf3e40c894f2e84b8cd3aa82d83765Yu Ping Hu} 608